3 #include "sparc-funcdef.h"
5 #define LANGUAGE_ASSEMBLY
9 #include "genesis/closure.h"
10 #include "genesis/fdefn.h"
11 #include "genesis/static-symbols.h"
12 #include "genesis/simple-fun.h"
14 #define load(sym, reg) \
15 sethi %hi(sym), reg; ld [reg+%lo(sym)], reg
16 #define store(reg, sym) \
17 sethi %hi(sym), reg_L0; st reg, [reg_L0+%lo(sym)]
20 #define FRAMESIZE 0x48
21 #define ST_FLUSH_WINDOWS 0x03
23 .global call_into_lisp
24 FUNCDEF(call_into_lisp)
26 save %sp, -FRAMESIZE, %sp
28 /* Flush all of C's register windows to the stack. */
31 /* Save the return address. */
34 /* Clear the descriptor regs. (See sparc/vm.lisp) */
41 mov reg_ZERO, reg_OCFP
43 mov reg_ZERO, reg_CODE
48 /* Set the pseudo-atomic flag. */
51 /* Turn off foreign function call. */
52 sethi %hi(foreign_function_call_active), reg_NL0
53 st reg_ZERO, [reg_NL0+%lo(foreign_function_call_active)]
55 /* Load the rest of lisp state. */
56 load(dynamic_space_free_pointer, reg_NL0)
57 add reg_NL0, reg_ALLOC, reg_ALLOC
58 load(current_binding_stack_pointer, reg_BSP)
59 load(current_control_stack_pointer, reg_CSP)
60 load(current_control_frame_pointer, reg_OCFP)
62 /* No longer atomic, and check for interrupt. */
63 sub reg_ALLOC, 4, reg_ALLOC
64 andcc reg_ALLOC, 3, reg_ZERO
66 tne PSEUDO_ATOMIC_TRAP
67 /* Pass in the args. */
71 ld [reg_CFP+0], reg_A0
72 ld [reg_CFP+4], reg_A1
73 ld [reg_CFP+8], reg_A2
74 ld [reg_CFP+12], reg_A3
75 ld [reg_CFP+16], reg_A4
76 ld [reg_CFP+20], reg_A5
79 set lra + OTHER_POINTER_LOWTAG, reg_LRA
81 /* Indirect closure */
82 ld [reg_LEXENV+CLOSURE_FUN_OFFSET], reg_CODE
84 jmp reg_CODE+SIMPLE_FUN_CODE_OFFSET
89 .word RETURN_PC_HEADER_WIDETAG
91 /* Blow off any extra values. */
95 /* Return the one value. */
98 /* Turn on pseudo_atomic */
99 add reg_ALLOC, 4, reg_ALLOC
101 /* Store LISP state */
102 andn reg_ALLOC, 7, reg_NL1
103 store(reg_NL1,dynamic_space_free_pointer)
104 store(reg_BSP,current_binding_stack_pointer)
105 store(reg_CSP,current_control_stack_pointer)
106 store(reg_CFP,current_control_frame_pointer)
108 /* No longer in Lisp. */
109 store(reg_NL1,foreign_function_call_active)
111 /* Were we interrupted? */
112 sub reg_ALLOC, 4, reg_ALLOC
113 andcc reg_ALLOC, 3, reg_ZERO
114 tne PSEUDO_ATOMIC_TRAP
116 /* Back to C we go. */
117 ld [%sp+FRAMESIZE-4], %i7
119 restore %sp, FRAMESIZE, %sp
124 /* Build a lisp stack frame */
125 mov reg_CFP, reg_OCFP
127 add reg_CSP, 32, reg_CSP
128 st reg_OCFP, [reg_CFP]
129 st reg_CODE, [reg_CFP+8]
131 /* Turn on pseudo-atomic. */
132 add reg_ALLOC, 4, reg_ALLOC
134 /* Convert the return address to an offset and save it on the stack. */
135 sub reg_LIP, reg_CODE, reg_L0
136 add reg_L0, OTHER_POINTER_LOWTAG, reg_L0
137 st reg_L0, [reg_CFP+4]
139 /* Store LISP state */
140 store(reg_BSP,current_binding_stack_pointer)
141 store(reg_CSP,current_control_stack_pointer)
142 store(reg_CFP,current_control_frame_pointer)
143 /* Use reg_CFP as a work register, and restore it */
144 andn reg_ALLOC, 7, reg_CFP
145 store(reg_CFP,dynamic_space_free_pointer)
146 load(current_control_frame_pointer, reg_CFP)
148 /* No longer in Lisp. */
149 store(reg_CSP,foreign_function_call_active)
151 /* Were we interrupted? */
152 sub reg_ALLOC, 4, reg_ALLOC
153 andcc reg_ALLOC, 3, reg_ZERO
154 tne PSEUDO_ATOMIC_TRAP
161 * Note: C calling conventions (32-bit) say that %o0 and %o1
162 * are used to return function results. In particular 64-bit
163 * results are in %o0 (hi) and %o1 (low).
166 /* Re-establish NIL */
172 /* No longer in foreign function call. */
173 sethi %hi(foreign_function_call_active), reg_NL2
174 st reg_ZERO, [reg_NL2+%lo(foreign_function_call_active)]
176 /* Load the rest of lisp state. */
177 load(dynamic_space_free_pointer, reg_NL2)
178 add reg_NL2, reg_ALLOC, reg_ALLOC
179 load(current_binding_stack_pointer, reg_BSP)
180 load(current_control_stack_pointer, reg_CSP)
181 load(current_control_frame_pointer, reg_CFP)
183 /* Get the return address back. */
184 ld [reg_CFP+4], reg_LIP
185 ld [reg_CFP+8], reg_CODE
186 add reg_LIP, reg_CODE, reg_LIP
187 sub reg_LIP, OTHER_POINTER_LOWTAG, reg_LIP
189 /* No longer atomic. */
190 sub reg_ALLOC, 4, reg_ALLOC
191 andcc reg_ALLOC, 3, reg_ZERO
192 tne PSEUDO_ATOMIC_TRAP
194 /* Reset the lisp stack. */
195 /* Note: OCFP is in one of the locals, it gets preserved across C. */
197 mov reg_OCFP, reg_CFP
199 /* And back into lisp. */
203 /* Lisp calling convention. notice the first .byte line.
205 .global undefined_tramp
206 FUNCDEF(undefined_tramp)
208 .byte 0, 0, 0, SIMPLE_FUN_HEADER_WIDETAG
209 undefined_tramp = . + 1
210 .word undefined_tramp
219 .byte UNDEFINED_FUN_ERROR
220 .byte 254, sc_DescriptorReg, 3
223 ld [reg_FDEFN+FDEFN_RAW_ADDR_OFFSET], reg_CODE
224 jmp reg_CODE+SIMPLE_FUN_CODE_OFFSET
227 /* Lisp calling convention. Notice the first .byte line.
229 .global closure_tramp
230 FUNCDEF(closure_tramp)
232 .byte 0, 0, 0, SIMPLE_FUN_HEADER_WIDETAG
233 closure_tramp = . + 1
240 ld [reg_FDEFN+FDEFN_FUN_OFFSET], reg_LEXENV
241 ld [reg_LEXENV+CLOSURE_FUN_OFFSET], reg_CODE
242 jmp reg_CODE+SIMPLE_FUN_CODE_OFFSET
247 * Function-end breakpoint magic.
252 .global fun_end_breakpoint_guts
253 fun_end_breakpoint_guts:
254 .word RETURN_PC_HEADER_WIDETAG
257 mov reg_CSP, reg_OCFP
258 add 4, reg_CSP, reg_CSP
267 .global fun_end_breakpoint_trap
268 fun_end_breakpoint_trap:
269 unimp trap_FunEndBreakpoint
273 .global fun_end_breakpoint_end
274 fun_end_breakpoint_end:
276 .global sparc_flush_icache
277 FUNCDEF(sparc_flush_icache)
280 1: iflush %o0 ! flush instruction cache
285 retl ! return from leaf routine
289 FUNCDEF(save_context)
291 ta ST_FLUSH_WINDOWS ! flush register windows
292 retl ! return from leaf routine