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. */
205 * Function-end breakpoint magic.
209 * For an explanation of the magic involved in function-end
210 * breakpoints, see the implementation in ppc-assem.S.
215 .global fun_end_breakpoint_guts
216 fun_end_breakpoint_guts:
217 .word RETURN_PC_HEADER_WIDETAG + 0x600
220 mov reg_CSP, reg_OCFP
221 add 4, reg_CSP, reg_CSP
230 .global fun_end_breakpoint_trap
231 fun_end_breakpoint_trap:
232 unimp trap_FunEndBreakpoint
236 .global fun_end_breakpoint_end
237 fun_end_breakpoint_end:
239 .global sparc_flush_icache
240 FUNCDEF(sparc_flush_icache)
243 1: iflush %o0 ! flush instruction cache
248 retl ! return from leaf routine
251 .global do_pending_interrupt
252 FUNCDEF(do_pending_interrupt)
253 do_pending_interrupt:
254 unimp trap_PendingInterrupt
259 FUNCDEF(save_context)
261 ta ST_FLUSH_WINDOWS ! flush register windows
262 retl ! return from leaf routine