OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [newlib/] [libgloss/] [mips/] [entry.S] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 39 lampret
/* entry.S - exception handler for emulating MIPS16 'entry' and 'exit'
2
   pseudo-instructions.  These instructions are generated by the compiler
3
   when the -mentry switch is used.  The instructions are not implemented
4
   in the MIPS16 CPU; hence the exception handler that emulates them.
5
 
6
   This module contains the following public functions:
7
 
8
   * void __install_entry_handler(void);
9
 
10
     This function installs the entry/exit exception handler.  It should
11
     be called before executing any MIPS16 functions that were compiled with
12
     -mentry, typically before main() is called.
13
 
14
   * void __remove_entry_handler(void);
15
 
16
     This function removes the entry/exit exception handler.  It should
17
     be called when the program is exiting, or when it is known that no
18
     more MIPS16 functions compiled with -mentry will be called.
19
*/
20
 
21 56 joel
#ifdef __mips16
22
/* This file contains 32 bit assembly code.  */
23
        .set nomips16
24
#endif
25
 
26 39 lampret
#include "regs.S"
27
 
28
#define CAUSE_EXCMASK   0x3c    /* mask for ExcCode in Cause Register */
29
#define EXC_RI          0x28    /* 101000 == 10 << 2 */
30
 
31
/* Set DEBUG to 1 to enable recording of the last 16 interrupt causes.  */
32
 
33
#define DEBUG 0
34
 
35
#if DEBUG
36
 
37
        .sdata
38
int_count:
39
        .space  4                       /* interrupt count modulo 16 */
40
int_cause:
41
        .space  4*16                    /* last 16 interrupt causes */
42
#endif
43
 
44
        .text
45
 
46
        .set    noreorder               /* Do NOT reorder instructions */
47
 
48
 
49
/* __entry_exit_handler - the reserved instruction exception handler
50
   that emulates the entry and exit instruction.  */
51
 
52
__entry_exit_handler:
53
        .set    noat                    /* Do NOT use at register */
54
#if DEBUG
55
/* Must avoid using 'la' pseudo-op because it uses gp register, which
56
   may not have a good value in an exception handler. */
57
 
58
#       la      k0, int_count           /* intcount = (intcount + 1) & 0xf */
59
        lui     k0 ,%hi(int_count)
60
        addiu   k0, k0 ,%lo(int_count)
61
        lw      k1, (k0)
62
        addiu   k1, k1, 1
63
        andi    k1, k1, 0x0f
64
        sw      k1, (k0)
65
#       la      k0, int_cause           /* k1 = &int_cause[intcount] */
66
        lui     k0, %hi(int_cause)
67
        addiu   k0, k0, %lo(int_cause)
68
        sll     k1, k1, 2
69
        add     k1, k1, k0
70
#endif
71
        mfc0    k0, C0_CAUSE            /* Fetch cause */
72
#if DEBUG
73
        sw      k0, -4(k1)              /* Save exception cause in buffer */
74
#endif
75
        mfc0    k1, C0_EPC              /* Check for Reserved Inst. without */
76
        and     k0, CAUSE_EXCMASK       /*   destroying any register */
77
        subu    k0, EXC_RI
78
        bne     k0, zero, check_others  /* Sorry, go do something else */
79
 
80
        and     k0, k1, 1               /* Check for TR mode (pc.0 = 1) */
81
        beq     k0, zero, ri_in_32      /* Sorry, RI in 32-bit mode */
82
        xor     k1, 1
83
 
84
/* Since we now are going to emulate or die, we can use all the T-registers */
85
/* that MIPS16 does not use (at, t0-t8), and we don't have to save them. */
86
 
87
        .set    at                      /* Now it's ok to use at again */
88
 
89
#if 0
90
        j       leave
91
        rfe
92
#endif
93
 
94
        lhu     t0, 0(k1)               /* Fetch the offending instruction */
95
        xor     t8, k1, 1               /* Prepare t8 for exit */
96
        and     t1, t0, 0xf81f          /* Check for entry/exit opcode */
97
        bne     t1, 0xe809, other_ri
98
 
99
deareg: and     t1, t0, 0x0700          /* Isolate the three a-bits */
100
        srl     t1, 6                   /* Adjust them so x4 is applied */
101
        slt     t2, t1, 17              /* See if this is the exit instruction */
102
        beqz    t2, doexit
103
        la      t2, savea
104
        subu    t2, t1
105
        jr      t2                      /* Jump into the instruction table */
106
        rfe                             /* We run the rest in user-mode */
107
 
108
                                        /* This is the entry instruction! */
109
        sw      a3, 12(sp)              /* 4: a0-a3 saved */
110
        sw      a2,  8(sp)              /* 3: a0-a2 saved */
111
        sw      a1,  4(sp)              /* 2: a0-a1 saved */
112
        sw      a0,  0(sp)              /* 1: a0    saved */
113
savea:                                  /* 0: No arg regs saved */
114
 
115
dera:   and     t1, t0, 0x0020          /* Isolate the save-ra bit */
116
        move    t7, sp                  /* Temporary SP */
117
        beq     t1, zero, desreg
118
        subu    sp, 32                  /* Default SP adjustment */
119
        sw      ra, -4(t7)
120
        subu    t7, 4
121
 
122
desreg: and     t1, t0, 0x00c0          /* Isolate the two s-bits */
123
        beq     t1, zero, leave
124
        subu    t1, 0x0040
125
        beq     t1, zero, leave         /* Only one to save... */
126
        sw      s0, -4(t7)              /* Do the first one */
127
        sw      s1, -8(t7)              /* Do the last one */
128
 
129
leave:  jr      t8                      /* Exit to unmodified EPC */
130
        nop                             /* Urgh - the only nop!! */
131
 
132
doexf0: mtc1    v0,$f0                  /* Copy float value */
133
        b       doex2
134
 
135
doexf1: mtc1    v1,$f0                  /* Copy double value */
136
        mtc1    v0,$f1
137
        b       doex2
138
 
139
doexit: slt     t2, t1, 21
140
        beq     t2, zero, doexf0
141
        slt     t2, t1, 25
142
        beq     t2, zero, doexf1
143
 
144
doex2:  and     t1, t0, 0x0020          /* Isolate ra bit */
145
        beq     t1, zero, dxsreg        /* t1 holds ra-bit */
146
        addu    t7, sp, 32              /* Temporary SP */
147
        lw      ra, -4(t7)
148
        subu    t7, 4
149
 
150
dxsreg: and     t1, t0, 0x00c0          /* Isolate the two s-bits */
151
        beq     t1, zero, leavex
152
        subu    t1, 0x0040
153
        beq     t1, zero, leavex        /* Only one to save... */
154
        lw      s0, -4(t7)              /* Do the first one */
155
        lw      s1, -8(t7)              /* Do the last one */
156
 
157
leavex: jr      ra                      /* Exit to ra */
158
        addu    sp, 32                  /* Clean up stack pointer */
159
 
160
/* Come here for exceptions we can't handle.  */
161
 
162
ri_in_32:
163
other_ri:
164
check_others:                           /* call the previous handler */
165
        la      k0,__previous
166
        jr      k0
167
        nop
168
 
169
__exception_code:
170
        .set noreorder
171
        la      k0, __entry_exit_handler
172
#       lui     k0, %hi(exception)
173
#       addiu   k0, k0, %lo(exception)
174
        jr      k0
175
        nop
176
        .set reorder
177
__exception_code_end:
178
 
179
        .data
180
__previous:
181
        .space  (__exception_code_end - __exception_code)
182
        .text
183
 
184
 
185
/* void __install_entry_handler(void)
186
 
187
   Install our entry/exit reserved instruction exception handler.
188
*/
189
        .ent    __install_entry_handler
190
        .globl  __install_entry_handler
191
__install_entry_handler:
192
        .set noreorder
193
        mfc0    a0,C0_SR
194
        nop
195
        li      a1,SR_BEV
196
        and     a1,a1,a0
197
        beq     a1,$0,baseaddr
198
        lui     a0,0x8000       /* delay slot */
199
        lui     a0,0xbfc0
200
        addiu   a0,a0,0x0100
201
baseaddr:
202
        addiu   a0,a0,0x080     /* a0 = base vector table address */
203
        li      a1,(__exception_code_end - __exception_code)
204
        la      a2,__exception_code
205
        la      a3,__previous
206
/* there must be a better way of doing this???? */
207
copyloop:
208
        lw      v0,0(a0)
209
        sw      v0,0(a3)
210
        lw      v0,0(a2)
211
        sw      v0,0(a0)
212
        addiu   a0,a0,4
213
        addiu   a2,a2,4
214
        addiu   a3,a3,4
215
        subu    a1,a1,4
216
        bne     a1,$0,copyloop
217
        nop
218
        j       ra
219
        nop
220
        .set reorder
221
        .end    __install_entry_handler
222
 
223
 
224
/* void __remove_entry_handler(void);
225
 
226
   Remove our entry/exit reserved instruction exception handler.
227
*/
228
 
229
        .ent    __remove_entry_handler
230
        .globl  __remove_entry_handler
231
__remove_entry_handler:
232
        .set noreorder
233
 
234
        mfc0    a0,C0_SR
235
        nop
236
        li      a1,SR_BEV
237
        and     a1,a1,a0
238
        beq     a1,$0,res_baseaddr
239
        lui     a0,0x8000       /* delay slot */
240
        lui     a0,0xbfc0
241
        addiu   a0,a0,0x0200
242
res_baseaddr:
243
        addiu   a0,a0,0x0180    /* a0 = base vector table address */
244
        li      a1,(__exception_code_end - __exception_code)
245
        la      a3,__previous
246
 
247
/* there must be a better way of doing this???? */
248
res_copyloop:
249
        lw      v0,0(a3)
250
        sw      v0,0(a0)
251
        addiu   a0,a0,4
252
        addiu   a3,a3,4
253
        subu    a1,a1,4
254
        bne     a1,$0,res_copyloop
255
        nop
256
        j       ra
257
        nop
258
        .set reorder
259
        .end    __remove_entry_handler
260
 
261
 
262
/* software_init_hook - install entry/exit handler and arrange to have it
263
   removed at exit.  This function is called by crt0.S.  */
264
 
265
        .text
266
        .globl  software_init_hook
267
        .ent    software_init_hook
268
software_init_hook:
269
        .set    noreorder
270
        subu    sp, sp, 8                       /* allocate stack space */
271
        sw      ra, 4(sp)                       /* save return address */
272
        jal     __install_entry_handler         /* install entry/exit handler */
273
        nop
274
        lui     a0, %hi(__remove_entry_handler) /* arrange for exit to */
275
        jal     atexit                          /*  de-install handler */
276
        addiu   a0, a0, %lo(__remove_entry_handler)     /* delay slot */
277
        lw      ra, 4(sp)                       /* get return address */
278
        j       ra                              /* return */
279
        addu    sp, sp, 8                       /* deallocate stack */
280
        .set    reorder
281
        .end    software_init_hook

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.