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