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

Subversion Repositories or1k

[/] [or1k/] [tags/] [alpha/] [newlib/] [libgloss/] [mips/] [entry.S] - Blame information for rev 1778

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

powered by: WebSVN 2.1.0

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