0.8.21.18:
[sbcl.git] / src / runtime / mips-assem.S
1 #include "sbcl.h"
2 #include "lispregs.h"
3 #include "globals.h"
4 #include "genesis/fdefn.h"
5 #include "genesis/closure.h"
6 #include "genesis/simple-fun.h"
7 #include "genesis/static-symbols.h"
8                 
9 #define zero $0
10 #define AT $1
11 #define v0 $2
12 #define v1 $3
13 #define a0 $4
14 #define a1 $5
15 #define a2 $6
16 #define a3 $7
17 #define t0 $8
18 #define t1 $9
19 #define t2 $10
20 #define t3 $11
21 #define t4 $12
22 #define t5 $13
23 #define t6 $14
24 #define t7 $15
25 #define s0 $16
26 #define s1 $17
27 #define s2 $18
28 #define s3 $19
29 #define s4 $20
30 #define s5 $21
31 #define s6 $22
32 #define s7 $23
33 #define t8 $24
34 #define t9 $25
35 #define k0 $26
36 #define k1 $27
37 #define gp $28
38 #define sp $29
39 #define s8 $30
40 #define ra $31
41
42 /*
43  * NESTED - declare nested routine entry point
44  */
45 #define NESTED(symbol, framesize, rpc)                  \
46                 .globl  symbol;                         \
47                 .align  2;                              \
48                 .type   symbol,@function;               \
49                 .ent    symbol,0;                       \
50 symbol:         .frame  sp, framesize, rpc
51
52 /*
53  * END - mark end of function
54  */
55 #define END(function)                                   \
56                 .end    function;                       \
57                 .size   function,.-function
58
59
60         .text
61         
62 /*
63  * Function to transfer control into lisp.
64  */
65 #define framesize 16*4
66         NESTED(call_into_lisp, framesize, ra)
67         subu    sp, framesize
68         /* Save all the C regs. */
69         .mask   0xd0ff0000, -4
70         sw      ra, framesize(sp)
71         sw      s8, framesize-4(sp)
72         sw      gp, framesize-8(sp)
73         sw      s7, framesize-12(sp)
74         sw      s6, framesize-16(sp)
75         sw      s5, framesize-20(sp)
76         sw      s4, framesize-24(sp)
77         sw      s3, framesize-28(sp)
78         sw      s2, framesize-32(sp)
79         sw      s1, framesize-36(sp)
80         sw      s0, framesize-40(sp)
81
82         /* Clear descriptor regs */
83         move    t0, zero
84         move    t1, zero
85         move    t2, zero
86         move    t3, zero
87         move    t4, zero
88         move    t5, zero
89         move    t6, zero
90         move    t7, zero
91         move    t8, zero
92         move    s0, zero
93         move    s1, zero
94         move    s2, zero
95         move    s3, zero
96         move    ra, zero
97
98         li      reg_NIL, NIL
99
100         /* Start pseudo-atomic. */
101         .set    noreorder
102         li      reg_NL4, 0
103         li      reg_ALLOC, 1
104         .set    reorder
105
106         /* No longer in foreign call. */
107         sw      zero, foreign_function_call_active
108
109         /* Load the allocation pointer, preserving the low-bit of alloc */
110         lw      reg_BSP, dynamic_space_free_pointer
111         add     reg_ALLOC, reg_BSP
112
113         /* Load the rest of the LISP state. */
114         lw      reg_BSP, current_binding_stack_pointer
115         lw      reg_CSP, current_control_stack_pointer
116         lw      reg_OCFP, current_control_frame_pointer
117
118         /* Check for interrupt */
119         .set    noreorder
120         bgez    reg_NL4, pa1
121         nop
122         break   0x10
123 pa1:
124         subu    reg_ALLOC, 1
125         .set    reorder
126
127         /* Pass in args */
128         move    reg_LEXENV, a0
129         move    reg_CFP, a1
130         sll     reg_NARGS, a2, 2
131         lw      reg_A0, 0(reg_CFP)
132         lw      reg_A1, 4(reg_CFP)
133         lw      reg_A2, 8(reg_CFP)
134         lw      reg_A3, 12(reg_CFP)
135         lw      reg_A4, 16(reg_CFP)
136         lw      reg_A5, 20(reg_CFP)
137
138         /* Calculate LRA */
139         la      reg_LRA, lra + OTHER_POINTER_LOWTAG
140
141         /* Indirect closure */
142         lw      reg_CODE, -1(reg_LEXENV)
143
144         /* Jump into lisp land. */
145         addu    reg_LIP, reg_CODE, 6*4 - FUN_POINTER_LOWTAG
146         jr      reg_LIP
147
148         .set    noreorder
149         .align  3
150 #ifdef irix
151         /* This particular KLUDGE is kept here as a reminder; for more
152         details, see irix-asm-munge.c from CMUCL's lisp directory.
153         Other examples have been deleted from later in the file in the
154         hope that they will not be needed. */
155 .globl  mipsmungelra /* for our munging afterwards in irix-asm-munge */
156 mipsmungelra:
157 #endif
158 lra:
159         .word   RETURN_PC_HEADER_WIDETAG
160
161         /* Multiple value return spot, clear stack */
162         move    reg_CSP, reg_OCFP
163         nop
164
165         /* Set pseudo-atomic flag. */
166         li      reg_NL4, 0
167         addu    reg_ALLOC, 1
168         .set    reorder
169
170         /* Save LISP registers. */
171         subu    reg_NL0, reg_ALLOC, 1
172         sw      reg_NL0, dynamic_space_free_pointer
173         sw      reg_BSP, current_binding_stack_pointer
174         sw      reg_CSP, current_control_stack_pointer
175         sw      reg_CFP, current_control_frame_pointer
176
177         /* Pass one return value back to C land. */ 
178         /* v0 is reg_ALLOC in this new world, so do this after saving
179            reg_ALLOC in dynamic_space_free_pointer */
180         move    v0, reg_A0
181
182         /* Back in foreign function call */
183         sw      reg_CFP, foreign_function_call_active
184
185         /* Check for interrupt */
186         .set    noreorder
187         bgez    reg_NL4, pa2
188         nop
189         break   0x10
190 pa2:
191         subu    reg_ALLOC, 1
192         .set    reorder
193
194         /* Restore C regs */
195         lw      ra, framesize(sp)
196         lw      s8, framesize-4(sp)
197         lw      gp, framesize-8(sp)
198         lw      s7, framesize-12(sp)
199         lw      s6, framesize-16(sp)
200         lw      s5, framesize-20(sp)
201         lw      s4, framesize-24(sp)
202         lw      s3, framesize-28(sp)
203         lw      s2, framesize-32(sp)
204         lw      s1, framesize-36(sp)
205         lw      s0, framesize-40(sp)
206
207         /* Restore C stack. */
208         addu    sp, framesize
209
210         /* Back we go. */
211         jr      ra
212
213         END(call_into_lisp)
214
215 /*
216  * Transfering control from Lisp into C
217  */
218         .globl  call_into_c
219         .align  2
220         .type   call_into_c,@function
221         .ent    call_into_c,0
222 call_into_c:
223         /* Set up a stack frame. */
224         move    reg_OCFP, reg_CFP
225         move    reg_CFP, reg_CSP
226         addu    reg_CSP, reg_CFP, 32
227         sw      reg_OCFP, 0(reg_CFP)
228         subu    reg_NL4, reg_LIP, reg_CODE
229         addu    reg_NL4, OTHER_POINTER_LOWTAG
230         sw      reg_NL4, 4(reg_CFP)
231         sw      reg_CODE, 8(reg_CFP)
232         sw      gp, 12(reg_CFP)
233
234         /* Note: the C stack is already set up. */
235
236         /* Set the pseudo-atomic flag. */
237         .set    noreorder
238         li      reg_NL4, 0
239         addu    reg_ALLOC, 1
240         .set    reorder
241
242         /* Save lisp state. */
243         subu    t0, reg_ALLOC, 1
244         sw      t0, dynamic_space_free_pointer
245         sw      reg_BSP, current_binding_stack_pointer
246         sw      reg_CSP, current_control_stack_pointer
247         sw      reg_CFP, current_control_frame_pointer
248
249         /* Mark us as in C land. */
250         sw      reg_CSP, foreign_function_call_active
251
252         /* Were we interrupted? */
253         .set    noreorder
254         bgez    reg_NL4, pa3
255         nop
256         break   0x10
257 pa3:
258         subu    reg_ALLOC, 1
259         .set    reorder
260
261         /* Into C land we go. */
262         move    t9, reg_CFUNC
263         jalr    t9
264         nop
265
266         lw      gp, 12(reg_CFP)
267         
268         /* Clear unsaved descriptor regs */
269         move    t0, zero
270         move    t1, zero
271         move    t2, zero
272         move    t3, zero
273         move    t4, zero
274         move    t5, zero
275         move    t6, zero
276         move    t7, zero
277         move    t8, zero
278         move    s0, zero
279         move    s2, zero
280         move    s3, zero
281         move    ra, zero
282
283         /* Turn on pseudo-atomic. */
284         .set    noreorder
285         li      reg_NL4, 0
286         li      reg_ALLOC, 1
287         .set    reorder
288
289         /* Mark us at in Lisp land. */
290         sw      zero, foreign_function_call_active
291
292         /* Restore ALLOC, preserving pseudo-atomic-atomic */
293         lw      a0, dynamic_space_free_pointer
294         addu    reg_ALLOC, a0
295
296         /* Check for interrupt */
297         .set    noreorder
298         bgez    reg_NL4, pa4
299         nop
300         break   0x10
301 pa4:
302         subu    reg_ALLOC, 1
303         .set    reorder
304
305         /* Restore LRA & CODE (they may have been GC'ed) */
306         lw      reg_CODE, 8(reg_CFP)
307         lw      a0, 4(reg_CFP)
308         subu    a0, OTHER_POINTER_LOWTAG
309         addu    reg_LIP, reg_CODE, a0
310
311         /* Reset the lisp stack. */
312         /* Note: OCFP and CFP are in saved regs. */
313         move    reg_CSP, reg_CFP
314         move    reg_CFP, reg_OCFP
315
316         /* Return to LISP. */
317         j       reg_LIP
318
319         END(call_into_c)
320
321         .globl  start_of_tramps
322 start_of_tramps:
323
324 /*
325  * The undefined-function trampoline.
326  */
327         .globl  undefined_tramp
328         .ent    undefined_tramp
329 undefined_tramp:
330         break   10
331         .byte    4
332         .byte    UNDEFINED_FUN_ERROR
333         .byte    254
334         .byte    (0xc0 + sc_DescriptorReg)
335         .byte    1
336         .align 2
337         .end    undefined_tramp
338
339 /*
340  * The closure trampoline.
341  */
342         .globl  closure_tramp
343         .ent    closure_tramp
344 closure_tramp:
345         lw      reg_LEXENV, FDEFN_FUN_OFFSET(reg_FDEFN)
346         lw      reg_L0, CLOSURE_FUN_OFFSET(reg_LEXENV)
347         addu    reg_LIP, reg_L0, SIMPLE_FUN_CODE_OFFSET
348         j       reg_LIP
349         .end    closure_tramp
350
351         .globl  end_of_tramps
352 end_of_tramps:
353
354
355 /*
356  * Function-end breakpoint magic.
357  */
358
359         .align  2
360         .set    noreorder
361         .globl  function_end_breakpoint_guts
362 fun_end_breakpoint_guts:
363         .word   RETURN_PC_HEADER_WIDETAG
364         
365         beq     zero, zero, 1f
366         nop
367         move    reg_OCFP, reg_CSP
368         addu    reg_CSP, 4
369         li      reg_NARGS, 4
370         move    reg_A1, reg_NIL
371         move    reg_A2, reg_NIL
372         move    reg_A3, reg_NIL
373         move    reg_A4, reg_NIL
374         move    reg_A5, reg_NIL
375 1:
376
377         .globl  fun_end_breakpoint_trap
378 fun_end_breakpoint_trap:
379         break   trap_FunEndBreakpoint
380         beq     zero, zero, 1b
381         nop
382
383         .globl  fun_end_breakpoint_end
384 fun_end_breakpoint_end:
385         .set    reorder