3 #include "sparc-funcdef.h"
5 #define LANGUAGE_ASSEMBLY
9 #include "genesis/closure.h"
10 #include "genesis/funcallable-instance.h"
11 #include "genesis/fdefn.h"
12 #include "genesis/static-symbols.h"
13 #include "genesis/simple-fun.h"
15 #define load(sym, reg) \
16 sethi %hi(sym), reg; ld [reg+%lo(sym)], reg
17 #define store(reg, sym) \
18 sethi %hi(sym), reg_L0; st reg, [reg_L0+%lo(sym)]
21 #define FRAMESIZE 0x48
22 #define ST_FLUSH_WINDOWS 0x03
24 .global call_into_lisp
25 FUNCDEF(call_into_lisp)
27 save %sp, -FRAMESIZE, %sp
29 /* Flush all of C's register windows to the stack. */
32 /* Save the return address. */
35 /* Clear the descriptor regs. (See sparc/vm.lisp) */
42 mov reg_ZERO, reg_OCFP
44 mov reg_ZERO, reg_CODE
49 /* Set the pseudo-atomic flag. */
52 /* Turn off foreign function call. */
53 sethi %hi(foreign_function_call_active), reg_NL0
54 st reg_ZERO, [reg_NL0+%lo(foreign_function_call_active)]
56 /* Load the rest of lisp state. */
57 load(dynamic_space_free_pointer, reg_NL0)
58 add reg_NL0, reg_ALLOC, reg_ALLOC
59 load(current_binding_stack_pointer, reg_BSP)
60 load(current_control_stack_pointer, reg_CSP)
61 load(current_control_frame_pointer, reg_OCFP)
63 /* No longer atomic, and check for interrupt. */
64 sub reg_ALLOC, 4, reg_ALLOC
65 andcc reg_ALLOC, 3, reg_ZERO
67 tne PSEUDO_ATOMIC_TRAP
68 /* Pass in the args. */
72 ld [reg_CFP+0], reg_A0
73 ld [reg_CFP+4], reg_A1
74 ld [reg_CFP+8], reg_A2
75 ld [reg_CFP+12], reg_A3
76 ld [reg_CFP+16], reg_A4
77 ld [reg_CFP+20], reg_A5
80 set lra + OTHER_POINTER_LOWTAG, reg_LRA
82 /* Indirect closure */
83 ld [reg_LEXENV+CLOSURE_FUN_OFFSET], reg_CODE
85 jmp reg_CODE+SIMPLE_FUN_CODE_OFFSET
90 .word RETURN_PC_HEADER_WIDETAG
92 /* Blow off any extra values. */
96 /* Return the one value. */
99 /* Turn on pseudo_atomic */
100 add reg_ALLOC, 4, reg_ALLOC
102 /* Store LISP state */
103 andn reg_ALLOC, 7, reg_NL1
104 store(reg_NL1,dynamic_space_free_pointer)
105 store(reg_BSP,current_binding_stack_pointer)
106 store(reg_CSP,current_control_stack_pointer)
107 store(reg_CFP,current_control_frame_pointer)
109 /* No longer in Lisp. */
110 store(reg_NL1,foreign_function_call_active)
112 /* Were we interrupted? */
113 sub reg_ALLOC, 4, reg_ALLOC
114 andcc reg_ALLOC, 3, reg_ZERO
115 tne PSEUDO_ATOMIC_TRAP
117 /* Back to C we go. */
118 ld [%sp+FRAMESIZE-4], %i7
120 restore %sp, FRAMESIZE, %sp
125 /* Build a lisp stack frame */
126 mov reg_CFP, reg_OCFP
128 add reg_CSP, 32, reg_CSP
129 st reg_OCFP, [reg_CFP]
130 st reg_CODE, [reg_CFP+8]
132 /* Turn on pseudo-atomic. */
133 add reg_ALLOC, 4, reg_ALLOC
135 /* Convert the return address to an offset and save it on the stack. */
136 sub reg_LIP, reg_CODE, reg_L0
137 add reg_L0, OTHER_POINTER_LOWTAG, reg_L0
138 st reg_L0, [reg_CFP+4]
140 /* Store LISP state */
141 store(reg_BSP,current_binding_stack_pointer)
142 store(reg_CSP,current_control_stack_pointer)
143 store(reg_CFP,current_control_frame_pointer)
144 /* Use reg_CFP as a work register, and restore it */
145 andn reg_ALLOC, 7, reg_CFP
146 store(reg_CFP,dynamic_space_free_pointer)
147 load(current_control_frame_pointer, reg_CFP)
149 /* No longer in Lisp. */
150 store(reg_CSP,foreign_function_call_active)
152 /* Were we interrupted? */
153 sub reg_ALLOC, 4, reg_ALLOC
154 andcc reg_ALLOC, 3, reg_ZERO
155 tne PSEUDO_ATOMIC_TRAP
162 * Note: C calling conventions (32-bit) say that %o0 and %o1
163 * are used to return function results. In particular 64-bit
164 * results are in %o0 (hi) and %o1 (low).
167 /* Re-establish NIL */
173 /* No longer in foreign function call. */
174 sethi %hi(foreign_function_call_active), reg_NL2
175 st reg_ZERO, [reg_NL2+%lo(foreign_function_call_active)]
177 /* Load the rest of lisp state. */
178 load(dynamic_space_free_pointer, reg_NL2)
179 add reg_NL2, reg_ALLOC, reg_ALLOC
180 load(current_binding_stack_pointer, reg_BSP)
181 load(current_control_stack_pointer, reg_CSP)
182 load(current_control_frame_pointer, reg_CFP)
184 /* Get the return address back. */
185 ld [reg_CFP+4], reg_LIP
186 ld [reg_CFP+8], reg_CODE
187 add reg_LIP, reg_CODE, reg_LIP
188 sub reg_LIP, OTHER_POINTER_LOWTAG, reg_LIP
190 /* No longer atomic. */
191 sub reg_ALLOC, 4, reg_ALLOC
192 andcc reg_ALLOC, 3, reg_ZERO
193 tne PSEUDO_ATOMIC_TRAP
195 /* Reset the lisp stack. */
196 /* Note: OCFP is in one of the locals, it gets preserved across C. */
198 mov reg_OCFP, reg_CFP
200 /* And back into lisp. */
204 /* Lisp calling convention. notice the first .byte line.
206 .global undefined_tramp
207 FUNCDEF(undefined_tramp)
209 .byte 0, 0, 0, SIMPLE_FUN_HEADER_WIDETAG
210 undefined_tramp = . + 1
211 .word undefined_tramp
221 .byte UNDEFINED_FUN_ERROR
222 .byte 254, sc_DescriptorReg, 3
225 ld [reg_FDEFN+FDEFN_RAW_ADDR_OFFSET], reg_CODE
226 jmp reg_CODE+SIMPLE_FUN_CODE_OFFSET
229 /* Lisp calling convention. Notice the first .byte line.
231 .global closure_tramp
232 FUNCDEF(closure_tramp)
234 .byte 0, 0, 0, SIMPLE_FUN_HEADER_WIDETAG
235 closure_tramp = . + 1
243 ld [reg_FDEFN+FDEFN_FUN_OFFSET], reg_LEXENV
244 ld [reg_LEXENV+CLOSURE_FUN_OFFSET], reg_CODE
245 jmp reg_CODE+SIMPLE_FUN_CODE_OFFSET
248 .global funcallable_instance_tramp
249 FUNCDEF(funcallable_instance_tramp)
251 .word SIMPLE_FUN_HEADER_WIDETAG
252 funcallable_instance_tramp = . + 1
253 .word funcallable_instance_tramp
260 ld [reg_LEXENV+FUNCALLABLE_INSTANCE_FUNCTION_OFFSET], reg_LEXENV
261 ld [reg_LEXENV+CLOSURE_FUN_OFFSET], reg_CODE
262 jmp reg_CODE+SIMPLE_FUN_CODE_OFFSET
265 * Function-end breakpoint magic.
269 * For an explanation of the magic involved in function-end
270 * breakpoints, see the implementation in ppc-assem.S.
275 .global fun_end_breakpoint_guts
276 fun_end_breakpoint_guts:
277 .word RETURN_PC_HEADER_WIDETAG + 0x800
280 mov reg_CSP, reg_OCFP
281 add 4, reg_CSP, reg_CSP
290 .global fun_end_breakpoint_trap
291 fun_end_breakpoint_trap:
292 unimp trap_FunEndBreakpoint
296 .global fun_end_breakpoint_end
297 fun_end_breakpoint_end:
299 .global sparc_flush_icache
300 FUNCDEF(sparc_flush_icache)
303 1: iflush %o0 ! flush instruction cache
308 retl ! return from leaf routine
311 .global do_pending_interrupt
312 FUNCDEF(do_pending_interrupt)
313 do_pending_interrupt:
314 unimp trap_PendingInterrupt
319 * Save the FPU state. %o0 contains a pointer to where we can
324 * Note we only save the 16 double-float registers (which saves
325 * the 32 single-float values too, I think). If we're compiling for
326 * a sparc v9, the Lisp code can actually use all 32 double-float
327 * registers. For later.
337 std %f10, [%o0 + 4*10]
338 std %f12, [%o0 + 4*12]
339 std %f14, [%o0 + 4*14]
340 std %f16, [%o0 + 4*16]
341 std %f18, [%o0 + 4*18]
342 std %f20, [%o0 + 4*20]
343 std %f22, [%o0 + 4*22]
344 std %f24, [%o0 + 4*24]
345 std %f26, [%o0 + 4*26]
346 std %f28, [%o0 + 4*28]
347 std %f30, [%o0 + 4*30]
348 #ifdef FEATURE_SPARC_V9
349 std %f32, [%o0 + 4*32]
350 std %f34, [%o0 + 4*34]
351 std %f36, [%o0 + 4*36]
352 std %f38, [%o0 + 4*38]
353 std %f40, [%o0 + 4*40]
354 std %f42, [%o0 + 4*42]
355 std %f44, [%o0 + 4*44]
356 std %f46, [%o0 + 4*46]
357 std %f48, [%o0 + 4*48]
358 std %f50, [%o0 + 4*50]
359 std %f52, [%o0 + 4*52]
360 std %f54, [%o0 + 4*54]
361 std %f56, [%o0 + 4*56]
362 std %f58, [%o0 + 4*58]
363 std %f60, [%o0 + 4*60]
364 std %f62, [%o0 + 4*62]
365 st %fsr, [%o0 + 4*64]
367 st %fsr, [%o0 + 4*32]
380 ldd [%o0 + 4*10], %f10
381 ldd [%o0 + 4*12], %f12
382 ldd [%o0 + 4*14], %f14
383 ldd [%o0 + 4*16], %f16
384 ldd [%o0 + 4*18], %f18
385 ldd [%o0 + 4*20], %f20
386 ldd [%o0 + 4*22], %f22
387 ldd [%o0 + 4*24], %f24
388 ldd [%o0 + 4*26], %f26
389 ldd [%o0 + 4*28], %f28
390 ldd [%o0 + 4*30], %f30
391 #ifdef FEATURE_SPARC_V9
392 ldd [%o0 + 4*32], %f32
393 ldd [%o0 + 4*34], %f34
394 ldd [%o0 + 4*36], %f36
395 ldd [%o0 + 4*38], %f38
396 ldd [%o0 + 4*40], %f40
397 ldd [%o0 + 4*42], %f42
398 ldd [%o0 + 4*44], %f44
399 ldd [%o0 + 4*46], %f46
400 ldd [%o0 + 4*48], %f48
401 ldd [%o0 + 4*50], %f50
402 ldd [%o0 + 4*52], %f52
403 ldd [%o0 + 4*54], %f54
404 ldd [%o0 + 4*56], %f56
405 ldd [%o0 + 4*58], %f58
406 ldd [%o0 + 4*60], %f60
407 ldd [%o0 + 4*62], %f62
408 ld [%o0 + 4*64], %fsr
410 ld [%o0 + 4*32], %fsr
416 FUNCDEF(save_context)
418 ta ST_FLUSH_WINDOWS ! flush register windows
419 retl ! return from leaf routine