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