0.9.1.36:
[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         /* Nested lisp -> C calls may have clobbered gp. */
184         lw      gp, framesize-16(sp)
185
186         /* Set the pseudo-atomic flag. */
187         li      reg_NL4, 0
188         addu    reg_ALLOC, 1
189         .set    reorder
190
191         /* Save LISP state. */
192         subu    reg_NL0, reg_ALLOC, 1
193         sw      reg_NL0, dynamic_space_free_pointer
194         sw      reg_BSP, current_binding_stack_pointer
195         sw      reg_CSP, current_control_stack_pointer
196         sw      reg_CFP, current_control_frame_pointer
197
198         /* Mark us as in C land. */
199         sw      reg_CSP, foreign_function_call_active
200
201         /* Check for interrupt */
202         .set    noreorder
203         bgez    reg_NL4, 1f
204          subu   reg_ALLOC, 1
205         break   0x10
206 1:      .set    reorder
207
208         /* Pass one return value back to C land. For a 64bit value, we may
209            need to clobber v1 aka reg_NL4. */
210         move    v0, reg_A0      # reg_CFUNC
211         move    v1, reg_A1      # reg_NL4
212
213         /* Restore C regs */
214         lw      ra, framesize-8(sp)
215         lw      s8, framesize-12(sp)
216         lw      s7, framesize-20(sp)
217         lw      s6, framesize-24(sp)
218         lw      s5, framesize-28(sp)
219         lw      s4, framesize-32(sp)
220         lw      s3, framesize-36(sp)
221         lw      s2, framesize-40(sp)
222         lw      s1, framesize-44(sp)
223         lw      s0, framesize-48(sp)
224
225         /* Restore C stack. */
226         addu    sp, framesize
227
228         /* Back we go. */
229         jr      ra
230
231         END(call_into_lisp)
232
233 /*
234  * Transfering control from Lisp into C
235  */
236         NESTED(call_into_c, 0, ra)
237         /* The stack frame was already set up from lisp. We have
238            to fake the correct gp value for this function, though. */
239         .set    noreorder
240         .set    noat
241         lui     gp, %hi(_gp_disp)
242         addiu   gp, %lo(_gp_disp)
243         lui     reg_NL3, %hi(call_into_c)
244         addiu   reg_NL3, %lo(call_into_c)
245         addu    gp, reg_NL3
246         .set    at
247         .set    reorder
248
249         move    reg_OCFP, reg_CFP
250         move    reg_CFP, reg_CSP
251         addu    reg_CSP, reg_CFP, 32
252
253         subu    reg_LIP, reg_CODE
254         addu    reg_LIP, OTHER_POINTER_LOWTAG
255         sw      reg_LIP, (reg_CFP)
256         sw      reg_CODE, 4(reg_CFP)
257         sw      gp, 8(reg_CFP)
258
259         /* Set the pseudo-atomic flag. */
260         .set    noreorder
261         li      reg_NL4, 0
262         addu    reg_ALLOC, 1
263         .set    reorder
264
265         /* Save LISP state. */
266         subu    reg_A0, reg_ALLOC, 1
267         sw      reg_A0, dynamic_space_free_pointer
268         sw      reg_BSP, current_binding_stack_pointer
269         sw      reg_CSP, current_control_stack_pointer
270         sw      reg_CFP, current_control_frame_pointer
271
272         /* Mark us as in C land. */
273         sw      reg_CSP, foreign_function_call_active
274
275         /* Check for interrupt */
276         .set    noreorder
277         bgez    reg_NL4, 1f
278          subu   reg_ALLOC, 1
279         break   0x10
280 1:      .set    reorder
281
282         /* Into C land we go. */
283         move    t9, reg_CFUNC
284         jalr    t9
285
286         lw      gp, 8(reg_CFP)
287         
288         /* Pass 64bit return value to lisp land. */ 
289         move    reg_NL0, v0             # reg_CFUNC
290         move    reg_NL1, v1             # reg_NL4
291
292         li      reg_NIL, NIL
293
294         /* Clear unsaved boxed descriptor regs */
295         li      reg_A0, 0               # t0
296         li      reg_A1, 0               # t1
297         li      reg_A2, 0               # t2
298         li      reg_A3, 0               # t3
299         li      reg_A4, 0               # t4
300         li      reg_A5, 0               # t5
301         li      reg_FDEFN, 0            # t6
302         li      reg_LEXENV, 0           # t7
303         li      reg_L1, 0               # t8
304
305         /* Turn on pseudo-atomic. */
306         .set    noreorder
307         li      reg_NL4, 0
308         li      reg_ALLOC, 1
309         .set    reorder
310
311         /* Mark us as in Lisp land. */
312         sw      zero, foreign_function_call_active
313
314         /* Load the allocation pointer, preserving the low-bit of alloc */
315         lw      reg_BSP, dynamic_space_free_pointer
316         addu    reg_ALLOC, reg_BSP
317
318         lw      reg_BSP, current_binding_stack_pointer
319
320         /* Restore LRA & CODE */
321         lw      reg_LIP, (reg_CFP)
322         lw      reg_CODE, 4(reg_CFP)
323         subu    reg_LIP, OTHER_POINTER_LOWTAG
324         addu    reg_LIP, reg_CODE
325
326         /* Check for interrupt */
327         .set    noreorder
328         bgez    reg_NL4, 1f
329          subu   reg_ALLOC, 1
330         break   0x10
331 1:      .set    reorder
332
333         /* Reset the lisp stack. */
334         /* Note: OCFP and CFP are in saved regs. */
335         move    reg_CSP, reg_CFP
336         move    reg_CFP, reg_OCFP
337
338         /* Return to LISP. */
339         jr      reg_LIP
340         END(call_into_c)
341
342         EXPORT(start_of_tramps)
343
344 /*
345  * The undefined-function trampoline.
346  */
347         LEAF(undefined_tramp)
348         break   trap_Error
349         .byte   4
350         .byte   UNDEFINED_FUN_ERROR
351         .byte   254
352         .byte   (0xc0 + sc_DescriptorReg)
353         .byte   1
354         .align  2
355         END(undefined_tramp)
356
357 /*
358  * The closure trampoline.
359  */
360         LEAF(closure_tramp)
361         lw      reg_LEXENV, FDEFN_FUN_OFFSET(reg_FDEFN)
362         lw      reg_L0, CLOSURE_FUN_OFFSET(reg_LEXENV)
363         addu    reg_LIP, reg_L0, SIMPLE_FUN_CODE_OFFSET
364         jr      reg_LIP
365         END(closure_tramp)
366
367         EXPORT(end_of_tramps)
368
369 /*
370  * Function-end breakpoint magic.
371  */
372         .align  3
373         LEAF(fun_end_breakpoint_guts)
374         .set    noreorder
375         .word   RETURN_PC_HEADER_WIDETAG
376
377         b       multiple_value_return
378          nop
379         .set    reorder
380
381         move    reg_OCFP, reg_CSP
382         addu    reg_CSP, 4
383         li      reg_NARGS, 4
384         move    reg_A1, reg_NIL
385         move    reg_A2, reg_NIL
386         move    reg_A3, reg_NIL
387         move    reg_A4, reg_NIL
388         move    reg_A5, reg_NIL
389
390 multiple_value_return:
391
392         FEXPORT(fun_end_breakpoint_trap)
393         break   trap_FunEndBreakpoint
394         b       multiple_value_return
395         EXPORT(fun_end_breakpoint_end)
396         END(fun_end_breakpoint_guts)