fixes for host gcc 4.6.1
[zpugcc/jano.git] / toolchain / gcc / libgloss / mips / entry.S
blob3630c552f89ad363b51153005909ccdd87f75618
1 /* 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.
6    This module contains the following public functions:
8    * void __install_entry_handler(void);
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.
14    * void __remove_entry_handler(void);
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.
21 #ifdef __mips16
22 /* This file contains 32 bit assembly code.  */
23         .set nomips16
24 #endif
26 #include "regs.S"
28 #define CAUSE_EXCMASK   0x3c    /* mask for ExcCode in Cause Register */
29 #define EXC_RI          0x28    /* 101000 == 10 << 2 */
31 /* Set DEBUG to 1 to enable recording of the last 16 interrupt causes.  */
33 #define DEBUG 0
35 #if DEBUG
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
44         .text
46         .set    noreorder               /* Do NOT reorder instructions */
49 /* __entry_exit_handler - the reserved instruction exception handler
50    that emulates the entry and exit instruction.  */
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 */
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                   
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. */
87         .set    at                      /* Now it's ok to use at again */
89 #if 0
90         j       leave
91         rfe
92 #endif
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
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 */
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 */
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
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 */
129 leave:  jr      t8                      /* Exit to unmodified EPC */
130         nop                             /* Urgh - the only nop!! */
132 doexf0: mtc1    v0,$f0                  /* Copy float value */
133         b       doex2
135 doexf1: mtc1    v1,$f0                  /* Copy double value */
136         mtc1    v0,$f1
137         b       doex2
139 doexit: slt     t2, t1, 21
140         beq     t2, zero, doexf0
141         slt     t2, t1, 25
142         beq     t2, zero, doexf1
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
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 */
157 leavex: jr      ra                      /* Exit to ra */
158         addu    sp, 32                  /* Clean up stack pointer */
160 /* Come here for exceptions we can't handle.  */
162 ri_in_32:
163 other_ri:
164 check_others:                           /* call the previous handler */
165         la      k0,__previous
166         jr      k0
167         nop
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:
179         .data
180 __previous:
181         .space  (__exception_code_end - __exception_code)
182         .text
185 /* void __install_entry_handler(void)
187    Install our entry/exit reserved instruction exception handler.
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
224 /* void __remove_entry_handler(void);
226    Remove our entry/exit reserved instruction exception handler.
229         .ent    __remove_entry_handler
230         .globl  __remove_entry_handler
231 __remove_entry_handler:
232         .set noreorder
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
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
262 /* software_init_hook - install entry/exit handler and arrange to have it
263    removed at exit.  This function is called by crt0.S.  */
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