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