2 // Mark the object as not requiring an executable stack.
3 .section .note.GNU-stack,"",%progbits
8 #include "sparc-funcdef.h"
10 #define LANGUAGE_ASSEMBLY
14 #include "genesis/closure.h"
15 #include "genesis/funcallable-instance.h"
16 #include "genesis/fdefn.h"
17 #include "genesis/static-symbols.h"
18 #include "genesis/simple-fun.h"
20 #define load(sym, reg) \
21 sethi %hi(sym), reg; ld [reg+%lo(sym)], reg
22 #define store(reg, sym) \
23 sethi %hi(sym), reg_L0; st reg, [reg_L0+%lo(sym)]
26 #define FRAMESIZE 0x48
27 #define ST_FLUSH_WINDOWS 0x03
29 .global call_into_lisp
30 FUNCDEF(call_into_lisp)
32 save %sp, -FRAMESIZE, %sp
34 /* Flush all of C's register windows to the stack. */
37 /* Save the return address. */
40 /* Clear the descriptor regs. (See sparc/vm.lisp) */
47 mov reg_ZERO, reg_OCFP
49 mov reg_ZERO, reg_CODE
54 /* Set the pseudo-atomic flag. */
57 /* Turn off foreign function call. */
58 sethi %hi(foreign_function_call_active), reg_NL0
59 st reg_ZERO, [reg_NL0+%lo(foreign_function_call_active)]
61 /* Load the rest of lisp state. */
62 load(dynamic_space_free_pointer, reg_NL0)
63 add reg_NL0, reg_ALLOC, reg_ALLOC
64 load(current_binding_stack_pointer, reg_BSP)
65 load(current_control_stack_pointer, reg_CSP)
66 load(current_control_frame_pointer, reg_OCFP)
68 /* No longer atomic, and check for interrupt. */
69 sub reg_ALLOC, 4, reg_ALLOC
70 andcc reg_ALLOC, 3, reg_ZERO
72 tne PSEUDO_ATOMIC_TRAP
73 /* Pass in the args. */
77 ld [reg_CFP+0], reg_A0
78 ld [reg_CFP+4], reg_A1
79 ld [reg_CFP+8], reg_A2
80 ld [reg_CFP+12], reg_A3
81 ld [reg_CFP+16], reg_A4
82 ld [reg_CFP+20], reg_A5
85 set lra + OTHER_POINTER_LOWTAG, reg_LRA
87 /* Indirect closure */
88 ld [reg_LEXENV+CLOSURE_FUN_OFFSET], reg_CODE
90 jmp reg_CODE+SIMPLE_FUN_CODE_OFFSET
95 .word RETURN_PC_WIDETAG
97 /* Blow off any extra values. */
101 /* Return the one value. */
104 /* Turn on pseudo_atomic */
105 add reg_ALLOC, 4, reg_ALLOC
107 /* Store LISP state */
108 andn reg_ALLOC, 7, reg_NL1
109 store(reg_NL1,dynamic_space_free_pointer)
110 store(reg_BSP,current_binding_stack_pointer)
111 store(reg_CSP,current_control_stack_pointer)
112 store(reg_CFP,current_control_frame_pointer)
114 /* No longer in Lisp. */
115 store(reg_NL1,foreign_function_call_active)
117 /* Were we interrupted? */
118 sub reg_ALLOC, 4, reg_ALLOC
119 andcc reg_ALLOC, 3, reg_ZERO
120 tne PSEUDO_ATOMIC_TRAP
122 /* Back to C we go. */
123 ld [%sp+FRAMESIZE-4], %i7
125 restore %sp, FRAMESIZE, %sp
130 /* Build a lisp stack frame */
131 mov reg_CFP, reg_OCFP
133 add reg_CSP, 32, reg_CSP
134 st reg_OCFP, [reg_CFP]
135 st reg_CODE, [reg_CFP+8]
137 /* Turn on pseudo-atomic. */
138 add reg_ALLOC, 4, reg_ALLOC
140 /* Convert the return address to an offset and save it on the stack. */
141 sub reg_LIP, reg_CODE, reg_L0
142 add reg_L0, OTHER_POINTER_LOWTAG, reg_L0
143 st reg_L0, [reg_CFP+4]
145 /* Store LISP state */
146 store(reg_BSP,current_binding_stack_pointer)
147 store(reg_CSP,current_control_stack_pointer)
148 store(reg_CFP,current_control_frame_pointer)
149 /* Use reg_CFP as a work register, and restore it */
150 andn reg_ALLOC, 7, reg_CFP
151 store(reg_CFP,dynamic_space_free_pointer)
152 load(current_control_frame_pointer, reg_CFP)
154 /* No longer in Lisp. */
155 store(reg_CSP,foreign_function_call_active)
157 /* Were we interrupted? */
158 sub reg_ALLOC, 4, reg_ALLOC
159 andcc reg_ALLOC, 3, reg_ZERO
160 tne PSEUDO_ATOMIC_TRAP
167 * Note: C calling conventions (32-bit) say that %o0 and %o1
168 * are used to return function results. In particular 64-bit
169 * results are in %o0 (hi) and %o1 (low).
172 /* Re-establish NIL */
178 /* No longer in foreign function call. */
179 sethi %hi(foreign_function_call_active), reg_NL2
180 st reg_ZERO, [reg_NL2+%lo(foreign_function_call_active)]
182 /* Load the rest of lisp state. */
183 load(dynamic_space_free_pointer, reg_NL2)
184 add reg_NL2, reg_ALLOC, reg_ALLOC
185 load(current_binding_stack_pointer, reg_BSP)
186 load(current_control_stack_pointer, reg_CSP)
187 load(current_control_frame_pointer, reg_CFP)
189 /* Get the return address back. */
190 ld [reg_CFP+4], reg_LIP
191 ld [reg_CFP+8], reg_CODE
192 add reg_LIP, reg_CODE, reg_LIP
193 sub reg_LIP, OTHER_POINTER_LOWTAG, reg_LIP
195 /* No longer atomic. */
196 sub reg_ALLOC, 4, reg_ALLOC
197 andcc reg_ALLOC, 3, reg_ZERO
198 tne PSEUDO_ATOMIC_TRAP
200 /* Reset the lisp stack. */
201 /* Note: OCFP is in one of the locals, it gets preserved across C. */
203 mov reg_OCFP, reg_CFP
205 /* And back into lisp. */
210 * Function-end breakpoint magic.
214 * For an explanation of the magic involved in function-end
215 * breakpoints, see the implementation in ppc-assem.S.
220 .global fun_end_breakpoint_guts
221 fun_end_breakpoint_guts:
222 .word RETURN_PC_WIDETAG + 0x600
225 mov reg_CSP, reg_OCFP
226 add 4, reg_CSP, reg_CSP
235 .global fun_end_breakpoint_trap
236 fun_end_breakpoint_trap:
237 unimp trap_FunEndBreakpoint
241 .global fun_end_breakpoint_end
242 fun_end_breakpoint_end:
244 .global sparc_flush_icache
245 FUNCDEF(sparc_flush_icache)
248 1: iflush %o0 ! flush instruction cache
253 retl ! return from leaf routine
256 .global do_pending_interrupt
257 FUNCDEF(do_pending_interrupt)
258 do_pending_interrupt:
259 unimp trap_PendingInterrupt
264 FUNCDEF(save_context)
266 ta ST_FLUSH_WINDOWS ! flush register windows
267 retl ! return from leaf routine