source: trunk/libs/newlib/src/libgloss/mips/entry.S @ 474

Last change on this file since 474 was 444, checked in by satin@…, 6 years ago

add newlib,libalmos-mkh, restructure shared_syscalls.h and mini-libc

File size: 7.0 KB
Line 
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.
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#ifdef __mips16
22/* This file contains 32 bit assembly code.  */
23        .set nomips16
24#endif
25
26#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
38int_count:
39        .space  4                       /* interrupt count modulo 16 */
40int_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
99deareg: 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 */
113savea:                                  /* 0: No arg regs saved */
114
115dera:   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
122desreg: 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
129leave:  jr      t8                      /* Exit to unmodified EPC */
130        nop                             /* Urgh - the only nop!! */
131
132doexf0: mtc1    v0,$f0                  /* Copy float value */
133        b       doex2
134
135doexf1: mtc1    v1,$f0                  /* Copy double value */
136        mtc1    v0,$f1
137        b       doex2
138
139doexit: slt     t2, t1, 21
140        beq     t2, zero, doexf0
141        slt     t2, t1, 25
142        beq     t2, zero, doexf1
143
144doex2:  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
150dxsreg: 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
157leavex: jr      ra                      /* Exit to ra */
158        addu    sp, 32                  /* Clean up stack pointer */
159
160/* Come here for exceptions we can't handle.  */
161
162ri_in_32:
163other_ri:
164check_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
201baseaddr:
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???? */
207copyloop:
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
242res_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???? */
248res_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
268software_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
Note: See TracBrowser for help on using the repository browser.