Replace %CODE-ENTRY-POINTS with an array, remove %SIMPLE-FUN-NEXT.
[sbcl.git] / src / runtime / mips-assem.S
blobae52500890b46a49273d44d321261b9292b5760e
1 /*
2  * very-low-level utilities for runtime support
3  */
5 /*
6  * This software is part of the SBCL system. See the README file for
7  * more information.
8  *
9  * This software is derived from the CMU CL system, which was
10  * written at Carnegie Mellon University and released into the
11  * public domain. The software is in the public domain and is
12  * provided with absolutely no warranty. See the COPYING and CREDITS
13  * files for more information.
14  */
16 #include "sbcl.h"
17 #include "lispregs.h"
18 #include "globals.h"
19 #include "genesis/fdefn.h"
20 #include "genesis/closure.h"
21 #include "genesis/funcallable-instance.h"
22 #include "genesis/simple-fun.h"
23 #include "genesis/static-symbols.h"
25 #define zero $0
26 #define AT $1
27 #define v0 $2
28 #define v1 $3
29 #define a0 $4
30 #define a1 $5
31 #define a2 $6
32 #define a3 $7
33 #define t0 $8
34 #define t1 $9
35 #define t2 $10
36 #define t3 $11
37 #define t4 $12
38 #define t5 $13
39 #define t6 $14
40 #define t7 $15
41 #define s0 $16
42 #define s1 $17
43 #define s2 $18
44 #define s3 $19
45 #define s4 $20
46 #define s5 $21
47 #define s6 $22
48 #define s7 $23
49 #define t8 $24
50 #define t9 $25
51 #define k0 $26
52 #define k1 $27
53 #define gp $28
54 #define sp $29
55 #define s8 $30
56 #define ra $31
59  * LEAF - declare leaf routine
60  */
61 #define LEAF(symbol)                                    \
62                 .globl  symbol;                         \
63                 .align  2;                              \
64                 .type   symbol,@function;               \
65                 .ent    symbol,0;                       \
66 symbol:         .frame  sp,0,ra
69  * NESTED - declare nested routine entry point
70  */
71 #define NESTED(symbol, framesize, rpc)                  \
72                 .globl  symbol;                         \
73                 .align  2;                              \
74                 .type   symbol,@function;               \
75                 .ent    symbol,0;                       \
76 symbol:         .frame  sp, framesize, rpc
79  * END - mark end of function
80  */
81 #define END(function)                                   \
82                 .end    function;                       \
83                 .size   function,.-function
86  * EXPORT - export definition of symbol
87  */
88 #define EXPORT(symbol)                                  \
89                 .globl  symbol;                         \
90 symbol:
93  * FEXPORT - export definition of a function symbol
94  */
95 #define FEXPORT(symbol)                                 \
96                 .globl  symbol;                         \
97                 .type   symbol,@function;               \
98 symbol:
101         .text
104  * Function to transfer control into lisp.
105  */
106 #define framesize 16*4
107         NESTED(call_into_lisp, framesize, ra)
108         .set    noreorder
109         .cpload t9
110         .set    reorder
111         subu    sp, framesize
113         /* Save all the C regs. */
114         .mask   0xc0ff0000, -8
115         sw      ra, framesize-8(sp)
116         sw      s8, framesize-12(sp)
117         /* No .cprestore, we don't want automatic gp restauration. */
118         sw      gp, framesize-16(sp)
119         sw      s7, framesize-20(sp)
120         sw      s6, framesize-24(sp)
121         sw      s5, framesize-28(sp)
122         sw      s4, framesize-32(sp)
123         sw      s3, framesize-36(sp)
124         sw      s2, framesize-40(sp)
125         sw      s1, framesize-44(sp)
126         sw      s0, framesize-48(sp)
128         li      reg_NIL, NIL
130         /* Clear unsaved boxed descriptor regs */
131         li      reg_FDEFN, 0            # t6
132         li      reg_L1, 0               # t8
134         /* Turn on pseudo-atomic. */
135         .set    noreorder
136         li      reg_NL4, 0
137         li      reg_ALLOC, 1
138         .set    reorder
140         /* Load the allocation pointer, preserving the low-bit of alloc */
141         lw      reg_BSP, dynamic_space_free_pointer
142         addu    reg_ALLOC, reg_BSP
144         /* Load the rest of the LISP state. */
145         lw      reg_BSP, current_binding_stack_pointer
146         lw      reg_CSP, current_control_stack_pointer
147         lw      reg_OCFP, current_control_frame_pointer
149         /* Check for interrupt */
150         .set    noreorder
151         bgez    reg_NL4, 1f
152          subu   reg_ALLOC, 1
153         break   0x0, trap_PendingInterrupt
154 1:      .set    reorder
156         /* Pass in args */
157         move    reg_LEXENV, a0
158         move    reg_CFP, a1
159         sll     reg_NARGS, a2, 2
160         lw      reg_A0, 0(reg_CFP)
161         lw      reg_A1, 4(reg_CFP)
162         lw      reg_A2, 8(reg_CFP)
163         lw      reg_A3, 12(reg_CFP)
164         lw      reg_A4, 16(reg_CFP)
165         lw      reg_A5, 20(reg_CFP)
167         /* Calculate LRA */
168         la      reg_LRA, lra + OTHER_POINTER_LOWTAG
170         /* Indirect closure */
171         lw      reg_CODE, CLOSURE_FUN_OFFSET(reg_LEXENV)
173         addu    reg_LIP, reg_CODE, SIMPLE_FUN_CODE_OFFSET
175         /* Mark us as in Lisp land. */
176         sw      zero, foreign_function_call_active
178         /* Jump into lisp land. */
179         jr      reg_LIP
181         .align  3
182         .set    noreorder
183 lra:    .word   RETURN_PC_HEADER_WIDETAG
185         /* Multiple value return spot, clear stack. */
186         move    reg_CSP, reg_OCFP
187         nop
189         /* Single value return spot. */
191         /* Nested lisp -> C calls may have clobbered gp. */
192         lw      gp, framesize-16(sp)
194         /* Mark us as in C land. */
195         sw      reg_CSP, foreign_function_call_active
197         /* Set the pseudo-atomic flag. */
198         li      reg_NL4, 0
199         addu    reg_ALLOC, 1
200         .set    reorder
202         /* Save LISP state. */
203         subu    reg_NL0, reg_ALLOC, 1
204         sw      reg_NL0, dynamic_space_free_pointer
205         sw      reg_BSP, current_binding_stack_pointer
206         sw      reg_CSP, current_control_stack_pointer
207         sw      reg_CFP, current_control_frame_pointer
209         /* Check for interrupt */
210         .set    noreorder
211         bgez    reg_NL4, 1f
212          subu   reg_ALLOC, 1
213         break   0x0, trap_PendingInterrupt
214 1:      .set    reorder
216         /* Pass one return value back to C land. For a 64bit value, we may
217            need to clobber v1 aka reg_NL4. */
218         move    v0, reg_A0      # reg_CFUNC
219         move    v1, reg_A1      # reg_NL4
221         /* Restore C regs */
222         lw      ra, framesize-8(sp)
223         lw      s8, framesize-12(sp)
224         lw      s7, framesize-20(sp)
225         lw      s6, framesize-24(sp)
226         lw      s5, framesize-28(sp)
227         lw      s4, framesize-32(sp)
228         lw      s3, framesize-36(sp)
229         lw      s2, framesize-40(sp)
230         lw      s1, framesize-44(sp)
231         lw      s0, framesize-48(sp)
233         /* Restore C stack. */
234         addu    sp, framesize
236         /* Back we go. */
237         jr      ra
239         END(call_into_lisp)
242  * Transfering control from Lisp into C
243  */
244         NESTED(call_into_c, 0, ra)
245         /* The C stack frame was already set up from lisp, and the
246            argument registers as well. We have to fake the correct
247            gp value for this function, though. */
248         .set    noreorder
249         /* reg_NL3 is AT. */
250         .set    noat
251         lui     gp, %hi(_gp_disp)
252         addiu   gp, %lo(_gp_disp)
253         lui     reg_NL3, %hi(call_into_c)
254         addiu   reg_NL3, %lo(call_into_c)
255         addu    gp, reg_NL3
256         .set    at
257         .set    reorder
259         /* Setup the lisp stack. */
260         move    reg_OCFP, reg_CFP
261         move    reg_CFP, reg_CSP
262         addu    reg_CSP, reg_CFP, 32
264         /* Mark us as in C land. */
265         sw      reg_CSP, foreign_function_call_active
267         /* Set the pseudo-atomic flag. */
268         .set    noreorder
269         li      reg_NL4, 0
270         addu    reg_ALLOC, 1
271         .set    reorder
273         /* Convert the return address to an offset and save it on the stack. */
274         subu    reg_NFP, reg_LIP, reg_CODE
275         addu    reg_NFP, OTHER_POINTER_LOWTAG
276         sw      reg_OCFP, (reg_CFP)
277         sw      reg_NFP, 4(reg_CFP)
278         sw      reg_CODE, 8(reg_CFP)
279         sw      gp, 12(reg_CFP) // should this be saved? on the control stack?
281         /* Save LISP state. */
282         subu    reg_A0, reg_ALLOC, 1
283         sw      reg_A0, dynamic_space_free_pointer
284         sw      reg_BSP, current_binding_stack_pointer
285         sw      reg_CSP, current_control_stack_pointer
286         sw      reg_CFP, current_control_frame_pointer
288         /* Check for interrupt */
289         .set    noreorder
290         bgez    reg_NL4, 1f
291         subu    reg_ALLOC, 1
292         break   0x0, trap_PendingInterrupt
293 1:      .set    reorder
295         /* Into C land we go. */
296         move    t9, reg_CFUNC           # reg_ALLOC
297         jalr    t9
299         lw      gp, 12(reg_CFP)
301         /* Pass 64bit return value to lisp land. */
302         move    reg_NL0, v0             # reg_CFUNC
303         move    reg_NL1, v1             # reg_NL4
305         /*
306          * Clear boxed descriptor registers before allowing an interrupt.
307          * We can't rely on C saving some of those registers, they might
308          * have been GCed in the meanwhile.
309          */
310         li      reg_A0, 0               # t0
311         li      reg_A1, 0               # t1
312         li      reg_A2, 0               # t2
313         li      reg_A3, 0               # t3
314         li      reg_A4, 0               # t4
315         li      reg_A5, 0               # t5
316         li      reg_FDEFN, 0            # t6
317         li      reg_LEXENV, 0           # t7
318         /*
319          * reg_NFP and reg_OCFP are pointing to fixed locations and are
320          * preserved by C.
321          */
322         li      reg_LRA, 0              # s2
323         li      reg_L0, 0               # s3
324         li      reg_L1, 0               # t8
325         li      reg_CODE, 0             # s8
326         li      reg_LIP, 0              # ra
328         /* Turn on pseudo-atomic. */
329         .set    noreorder
330         li      reg_NL4, 0
331         li      reg_ALLOC, 1
332         .set    reorder
334         /* Load the allocation pointer, preserving the low-bit of alloc */
335         lw      reg_BSP, dynamic_space_free_pointer
336         addu    reg_ALLOC, reg_BSP
338         lw      reg_BSP, current_binding_stack_pointer
340         /* Restore CODE */
341         lw      reg_CODE, 8(reg_CFP)
342         /* Setup the return address */
343         subu    reg_LIP, reg_NFP, OTHER_POINTER_LOWTAG
344         addu    reg_LIP, reg_CODE
346         /* Check for interrupt */
347         .set    noreorder
348         bgez    reg_NL4, 1f
349          subu   reg_ALLOC, 1
350         break   0x0, trap_PendingInterrupt
351 1:      .set    reorder
353         /* Reset the lisp stack. */
354         /* Note: OCFP and CFP are in saved regs. */
355         move    reg_CSP, reg_CFP
356         move    reg_CFP, reg_OCFP
358         /* Mark us as in Lisp land. */
359         sw      zero, foreign_function_call_active
361         /* Return to LISP. */
362         jr      reg_LIP
363         END(call_into_c)
366  * Function-end breakpoint magic. This is truely magic, the code is
367  * copied and has to be relocatable. It also needs a properly aligned
368  * header tag after the fun_end_breakpoint_guts symbol.
369  */
372  * For an explanation of the magic involved in function-end
373  * breakpoints, see the implementation in ppc-assem.S.
374  */
376         .align  3 /* minimum alignment for a lisp object */
377         LEAF(fun_end_breakpoint_guts)
378         .set    noreorder
379         .word   RETURN_PC_HEADER_WIDETAG + 0x600
380         b       multiple_value_return
381          nop
382         .set    reorder
384         /* single value return */
386         move    reg_OCFP, reg_CSP
387         addu    reg_CSP, 4
388         li      reg_NARGS, 4
389         move    reg_A1, reg_NIL
390         move    reg_A2, reg_NIL
391         move    reg_A3, reg_NIL
392         move    reg_A4, reg_NIL
393         move    reg_A5, reg_NIL
395 multiple_value_return:
397         FEXPORT(fun_end_breakpoint_trap)
398         .set    noreorder
399         b       multiple_value_return
400          break  0x0, trap_FunEndBreakpoint
401         .set    reorder
402         EXPORT(fun_end_breakpoint_end)
403         END(fun_end_breakpoint_guts)
406         .align  3 /* minimum alignment for a lisp object */
407         LEAF(do_pending_interrupt)
408         break   0x0, trap_PendingInterrupt
409         jr      reg_LIP
410         END(do_pending_interrupt)