%other-pointer-widetag derive-type: derive for simple-array.
[sbcl.git] / src / runtime / mips-assem.S
blobebaa57548d8d5583aaa6d927395b6c512d36cdfa
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 #ifdef __ELF__
17 // Mark the object as not requiring an executable stack.
18 .section .note.GNU-stack,"",%progbits
19 #endif
21 #include "genesis/sbcl.h"
22 #include "lispregs.h"
23 #include "genesis/closure.h"
24 #include "genesis/static-symbols.h"
25 #include "genesis/symbol.h"
27 #define zero $0
28 #define AT $1
29 #define v0 $2
30 #define v1 $3
31 #define a0 $4
32 #define a1 $5
33 #define a2 $6
34 #define a3 $7
35 #define t0 $8
36 #define t1 $9
37 #define t2 $10
38 #define t3 $11
39 #define t4 $12
40 #define t5 $13
41 #define t6 $14
42 #define t7 $15
43 #define s0 $16
44 #define s1 $17
45 #define s2 $18
46 #define s3 $19
47 #define s4 $20
48 #define s5 $21
49 #define s6 $22
50 #define s7 $23
51 #define t8 $24
52 #define t9 $25
53 #define k0 $26
54 #define k1 $27
55 //#define gp $28
56 #define sp $29
57 #define s8 $30
58 #define ra $31
61  * LEAF - declare leaf routine
62  */
63 #define LEAF(symbol)                                    \
64                 .globl  symbol;                         \
65                 .align  2;                              \
66                 .type   symbol,@function;               \
67                 .ent    symbol,0;                       \
68 symbol:         .frame  sp,0,ra
71  * NESTED - declare nested routine entry point
72  */
73 #define NESTED(symbol, framesize, rpc)                  \
74                 .globl  symbol;                         \
75                 .align  2;                              \
76                 .type   symbol,@function;               \
77                 .ent    symbol,0;                       \
78 symbol:         .frame  sp, framesize, rpc
81  * END - mark end of function
82  */
83 #define END(function)                                   \
84                 .end    function;                       \
85                 .size   function,.-function
88  * EXPORT - export definition of symbol
89  */
90 #define EXPORT(symbol)                                  \
91                 .globl  symbol;                         \
92 symbol:
95  * FEXPORT - export definition of a function symbol
96  */
97 #define FEXPORT(symbol)                                 \
98                 .globl  symbol;                         \
99                 .type   symbol,@function;               \
100 symbol:
102 /* zero (or anything non-nil) -> atomic=true and NIL -> atomic=false  */
103 #define BEGIN_PSEUDO_ATOMIC \
104         .set    noreorder ; \
105         sw      zero, (PSEUDO_ATOMIC_ATOMIC+SYMBOL_VALUE_OFFSET-NIL)(reg_NIL) ; \
106         .set    reorder
107 #define END_PSEUDO_ATOMIC(temp) \
108         .set    noreorder ; \
109         sw      reg_NIL, (PSEUDO_ATOMIC_ATOMIC+SYMBOL_VALUE_OFFSET-NIL)(reg_NIL) ; \
110         lw      temp, (PSEUDO_ATOMIC_INTERRUPTED+SYMBOL_VALUE_OFFSET-NIL)(reg_NIL) ; \
111         tne     zero, temp, 0 ; \
112         .set    reorder
114         .text
117  * Function to transfer control into lisp.
118  */
119 #define framesize 16*4
120         NESTED(call_into_lisp, framesize, ra)
121         .set    noreorder
122         .cpload t9
123         .set    reorder
124         subu    sp, framesize
126         /* Save all the C regs. */
127         .mask   0xc0ff0000, -8
128         sw      ra, framesize-8(sp)
129         sw      s8, framesize-12(sp)
130         sw      $gp, framesize-16(sp)
131         /* No .cprestore, we don't want automatic gp restoration. */
132         sw      s7, framesize-20(sp)
133         sw      s6, framesize-24(sp)
134         sw      s5, framesize-28(sp)
135         sw      s4, framesize-32(sp)
136         sw      s3, framesize-36(sp)
137         sw      s2, framesize-40(sp)
138         sw      s1, framesize-44(sp)
139         sw      s0, framesize-48(sp)
141         li      reg_NIL, NIL
143         /* Clear unsaved boxed descriptor regs */
144         li      reg_FDEFN, 0            # t6
145         li      reg_L1, 0               # t8
147         BEGIN_PSEUDO_ATOMIC
149         /* Load the rest of the LISP state. */
150         lw      reg_BSP, current_binding_stack_pointer
151         lw      reg_CSP, current_control_stack_pointer
152         lw      reg_OCFP, current_control_frame_pointer
154         END_PSEUDO_ATOMIC(reg_NL4)
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_INSTS_OFFSET
175         /* Mark us as in Lisp land. */
176         sw      zero, foreign_function_call_active
177         lw      reg_CARDBASE, gc_card_mark
179         /* Jump into lisp land. */
180         jr      reg_LIP
182         .align  3
183         .set    noreorder
184 lra:    .word   RETURN_PC_WIDETAG
186         /* Multiple value return spot, clear stack. */
187         move    reg_CSP, reg_OCFP
188         nop
190         /* Single value return spot. */
192         /* Nested lisp -> C calls may have clobbered gp. */
193         lw      $gp, framesize-16(sp)
195         /* Mark us as in C land. */
196         sw      reg_CSP, foreign_function_call_active
198         BEGIN_PSEUDO_ATOMIC
200         /* Save LISP state. */
201         sw      reg_BSP, current_binding_stack_pointer
202         sw      reg_CSP, current_control_stack_pointer
203         sw      reg_CFP, current_control_frame_pointer
205         END_PSEUDO_ATOMIC(reg_NL4)
207         /* Pass one return value back to C land. For a 64bit value, we may
208            need to clobber v1 aka reg_NL4. */
209         move    v0, reg_A0      # reg_CFUNC
210         move    v1, reg_A1      # reg_NL4
212         /* Restore C regs */
213         lw      ra, framesize-8(sp)
214         lw      s8, framesize-12(sp)
215         lw      s7, framesize-20(sp)
216         lw      s6, framesize-24(sp)
217         lw      s5, framesize-28(sp)
218         lw      s4, framesize-32(sp)
219         lw      s3, framesize-36(sp)
220         lw      s2, framesize-40(sp)
221         lw      s1, framesize-44(sp)
222         lw      s0, framesize-48(sp)
224         /* Restore C stack. */
225         addu    sp, framesize
227         /* Back we go. */
228         jr      ra
230         END(call_into_lisp)
233  * Transfering control from Lisp into C
234  */
235         NESTED(call_into_c, 0, ra)
237         /* Setup the lisp stack. */
238         move    reg_OCFP, reg_CFP
239         move    reg_CFP, reg_CSP
240         addu    reg_CSP, reg_CFP, 32
242         /* Mark us as in C land. */
243         sw      reg_CSP, foreign_function_call_active
245         BEGIN_PSEUDO_ATOMIC
247         /* Convert the return address to an offset and save it on the stack. */
248         subu    reg_NFP, reg_LIP, reg_CODE
249         addu    reg_NFP, OTHER_POINTER_LOWTAG
250         sw      reg_OCFP, (reg_CFP)
251         sw      reg_NFP, 4(reg_CFP)
252         sw      reg_CODE, 8(reg_CFP)
253         sw      $gp, 12(reg_CFP) // should this be saved? on the control stack?
255         /* Save LISP state. */
256         sw      reg_BSP, current_binding_stack_pointer
257         sw      reg_CSP, current_control_stack_pointer
258         sw      reg_CFP, current_control_frame_pointer
260         /* from the ABI: "When calling position independent functions
261            $25 must cotain the address of the called function." */
262         lw      $25, (reg_CFUNC) /* linkage-table indirection */
264         END_PSEUDO_ATOMIC(reg_NL4)
266         /* Into C land we go. */
267         jalr    $25
269         lw      $gp, 12(reg_CFP)
271         /* Pass 64bit return value to lisp land. */
272         move    reg_NL0, v0             # reg_CFUNC
273         move    reg_NL1, v1             # reg_NL4
275         /*
276          * Clear boxed descriptor registers before allowing an interrupt.
277          * We can't rely on C saving some of those registers, they might
278          * have been GCed in the meanwhile.
279          */
280         li      reg_A0, 0               # t0
281         li      reg_A1, 0               # t1
282         li      reg_A2, 0               # t2
283         li      reg_A3, 0               # t3
284         li      reg_A4, 0               # t4
285         li      reg_A5, 0               # t5
286         li      reg_FDEFN, 0            # t6
287         li      reg_LEXENV, 0           # t7
288         /*
289          * reg_NFP and reg_OCFP are pointing to fixed locations and are
290          * preserved by C.
291          */
292         li      reg_LRA, 0              # s2
293         li      reg_L0, 0               # s3
294         li      reg_L1, 0               # t8
295         li      reg_CODE, 0             # s8
296         li      reg_LIP, 0              # ra
298         BEGIN_PSEUDO_ATOMIC
300         lw      reg_BSP, current_binding_stack_pointer
302         /* Restore CODE */
303         lw      reg_CODE, 8(reg_CFP)
304         /* Setup the return address */
305         subu    reg_LIP, reg_NFP, OTHER_POINTER_LOWTAG
306         addu    reg_LIP, reg_CODE
308         END_PSEUDO_ATOMIC(reg_NL4)
310         /* Reset the lisp stack. */
311         /* Note: OCFP and CFP are in saved regs. */
312         move    reg_CSP, reg_CFP
313         move    reg_CFP, reg_OCFP
315         /* Mark us as in Lisp land. */
316         sw      zero, foreign_function_call_active
317         lw      reg_CARDBASE, gc_card_mark
319         /* Return to LISP. */
320         jr      reg_LIP
321         END(call_into_c)
324  * Function-end breakpoint magic. This is truely magic, the code is
325  * copied and has to be relocatable. It also needs a properly aligned
326  * header tag after the fun_end_breakpoint_guts symbol.
327  */
330  * For an explanation of the magic involved in function-end
331  * breakpoints, see the implementation in ppc-assem.S.
332  */
334         .align  3 /* minimum alignment for a lisp object */
335         LEAF(fun_end_breakpoint_guts)
336         .set    noreorder
337         .word   (((CODE_SIZE+1)&~1)<<N_WIDETAG_BITS)|RETURN_PC_WIDETAG
338         b       multiple_value_return
339          nop
340         .set    reorder
342         /* single value return */
344         move    reg_OCFP, reg_CSP
345         addu    reg_CSP, 4
346         li      reg_NARGS, 4
347         move    reg_A1, reg_NIL
348         move    reg_A2, reg_NIL
349         move    reg_A3, reg_NIL
350         move    reg_A4, reg_NIL
351         move    reg_A5, reg_NIL
353 multiple_value_return:
355         FEXPORT(fun_end_breakpoint_trap)
356         .set    noreorder
357         b       multiple_value_return
358          break  0x0, trap_FunEndBreakpoint
359         .set    reorder
360         EXPORT(fun_end_breakpoint_end)
361         END(fun_end_breakpoint_guts)
364         .align  3 /* minimum alignment for a lisp object */
365         LEAF(do_pending_interrupt)
366         break   0x0, trap_PendingInterrupt
367         jr      reg_LIP
368         END(do_pending_interrupt)