3 #define FUNCDEF(x) .type x,@function
5 #define LANGUAGE_ASSEMBLY
11 #define load(sym, reg) \
12 sethi %hi(sym), reg; ld [reg+%lo(sym)], reg
13 #define store(reg, sym) \
14 sethi %hi(sym), reg_L0; st reg, [reg_L0+%lo(sym)]
17 #define FRAMESIZE 0x48
18 #define ST_FLUSH_WINDOWS 0x03
20 .global call_into_lisp
21 FUNCDEF(call_into_lisp)
23 save %sp, -FRAMESIZE, %sp
25 /* Flush all of C's register windows to the stack. */
28 /* Save the return address. */
31 /* Clear the descriptor regs. (See sparc/vm.lisp) */
38 mov reg_ZERO, reg_OCFP
40 mov reg_ZERO, reg_CODE
45 /* Set the pseudo-atomic flag. */
48 /* Turn off foreign function call. */
49 sethi %hi(foreign_function_call_active), reg_NL0
50 st reg_ZERO, [reg_NL0+%lo(foreign_function_call_active)]
52 /* Load the rest of lisp state. */
53 load(dynamic_space_free_pointer, reg_NL0)
54 add reg_NL0, reg_ALLOC, reg_ALLOC
55 load(current_binding_stack_pointer, reg_BSP)
56 load(current_control_stack_pointer, reg_CSP)
57 load(current_control_frame_pointer, reg_OCFP)
59 /* No longer atomic, and check for interrupt. */
60 sub reg_ALLOC, 4, reg_ALLOC
61 andcc reg_ALLOC, 3, reg_ZERO
63 tne PSEUDO_ATOMIC_TRAP
64 /* Pass in the args. */
68 ld [reg_CFP+0], reg_A0
69 ld [reg_CFP+4], reg_A1
70 ld [reg_CFP+8], reg_A2
71 ld [reg_CFP+12], reg_A3
72 ld [reg_CFP+16], reg_A4
73 ld [reg_CFP+20], reg_A5
76 set lra + OTHER_POINTER_LOWTAG, reg_LRA
78 /* Indirect closure */
79 ld [reg_LEXENV+CLOSURE_FUN_OFFSET], reg_CODE
81 jmp reg_CODE+SIMPLE_FUN_CODE_OFFSET
86 .word RETURN_PC_HEADER_WIDETAG
88 /* Blow off any extra values. */
92 /* Return the one value. */
95 /* Turn on pseudo_atomic */
96 add reg_ALLOC, 4, reg_ALLOC
98 /* Store LISP state */
99 andn reg_ALLOC, 7, reg_NL1
100 store(reg_NL1,dynamic_space_free_pointer)
101 store(reg_BSP,current_binding_stack_pointer)
102 store(reg_CSP,current_control_stack_pointer)
103 store(reg_CFP,current_control_frame_pointer)
105 /* No longer in Lisp. */
106 store(reg_NL1,foreign_function_call_active)
108 /* Were we interrupted? */
109 sub reg_ALLOC, 4, reg_ALLOC
110 andcc reg_ALLOC, 3, reg_ZERO
111 tne PSEUDO_ATOMIC_TRAP
113 /* Back to C we go. */
114 ld [%sp+FRAMESIZE-4], %i7
116 restore %sp, FRAMESIZE, %sp
121 /* Build a lisp stack frame */
122 mov reg_CFP, reg_OCFP
124 add reg_CSP, 32, reg_CSP
125 st reg_OCFP, [reg_CFP]
126 st reg_CODE, [reg_CFP+8]
128 /* Turn on pseudo-atomic. */
129 add reg_ALLOC, 4, reg_ALLOC
131 /* Convert the return address to an offset and save it on the stack. */
132 sub reg_LIP, reg_CODE, reg_L0
133 add reg_L0, OTHER_POINTER_LOWTAG, reg_L0
134 st reg_L0, [reg_CFP+4]
136 /* Store LISP state */
137 store(reg_BSP,current_binding_stack_pointer)
138 store(reg_CSP,current_control_stack_pointer)
139 store(reg_CFP,current_control_frame_pointer)
140 /* Use reg_CFP as a work register, and restore it */
141 andn reg_ALLOC, 7, reg_CFP
142 store(reg_CFP,dynamic_space_free_pointer)
143 load(current_control_frame_pointer, reg_CFP)
145 /* No longer in Lisp. */
146 store(reg_CSP,foreign_function_call_active)
148 /* Were we interrupted? */
149 sub reg_ALLOC, 4, reg_ALLOC
150 andcc reg_ALLOC, 3, reg_ZERO
151 tne PSEUDO_ATOMIC_TRAP
158 * Note: C calling conventions (32-bit) say that %o0 and %o1
159 * are used to return function results. In particular 64-bit
160 * results are in %o0 (hi) and %o1 (low).
163 /* Re-establish NIL */
169 /* No longer in foreign function call. */
170 sethi %hi(foreign_function_call_active), reg_NL2
171 st reg_ZERO, [reg_NL2+%lo(foreign_function_call_active)]
173 /* Load the rest of lisp state. */
174 load(dynamic_space_free_pointer, reg_NL2)
175 add reg_NL2, reg_ALLOC, reg_ALLOC
176 load(current_binding_stack_pointer, reg_BSP)
177 load(current_control_stack_pointer, reg_CSP)
178 load(current_control_frame_pointer, reg_CFP)
180 /* Get the return address back. */
181 ld [reg_CFP+4], reg_LIP
182 ld [reg_CFP+8], reg_CODE
183 add reg_LIP, reg_CODE, reg_LIP
184 sub reg_LIP, OTHER_POINTER_LOWTAG, reg_LIP
186 /* No longer atomic. */
187 sub reg_ALLOC, 4, reg_ALLOC
188 andcc reg_ALLOC, 3, reg_ZERO
189 tne PSEUDO_ATOMIC_TRAP
191 /* Reset the lisp stack. */
192 /* Note: OCFP is in one of the locals, it gets preserved across C. */
194 mov reg_OCFP, reg_CFP
196 /* And back into lisp. */
200 .global undefined_tramp
201 FUNCDEF(undefined_tramp)
203 .byte 0, 0, 0, SIMPLE_FUN_HEADER_WIDETAG
204 undefined_tramp = . + 1
205 .word undefined_tramp
214 .byte UNDEFINED_FUN_ERROR
215 .byte 254, sc_DescriptorReg, 3
218 ld [reg_FDEFN+FDEFN_RAW_ADDR_OFFSET], reg_CODE
219 jmp reg_CODE+SIMPLE_FUN_CODE_OFFSET
222 .global closure_tramp
223 FUNCDEF(closure_tramp)
225 .byte 0, 0, 0, SIMPLE_FUN_HEADER_WIDETAG
226 closure_tramp = . + 1
233 ld [reg_FDEFN+FDEFN_FUN_OFFSET], reg_LEXENV
234 ld [reg_LEXENV+CLOSURE_FUN_OFFSET], reg_CODE
235 jmp reg_CODE+SIMPLE_FUN_CODE_OFFSET
240 * Function-end breakpoint magic.
245 .global fun_end_breakpoint_guts
246 fun_end_breakpoint_guts:
247 .word RETURN_PC_HEADER_WIDETAG
250 mov reg_CSP, reg_OCFP
251 add 4, reg_CSP, reg_CSP
260 .global fun_end_breakpoint_trap
261 fun_end_breakpoint_trap:
262 unimp trap_FunEndBreakpoint
266 .global fun_end_breakpoint_end
267 fun_end_breakpoint_end:
269 .global sparc_flush_icache
270 FUNCDEF(sparc_flush_icache)
273 1: iflush %o0 ! flush instruction cache
278 retl ! return from leaf routine
282 FUNCDEF(save_context)
284 ta ST_FLUSH_WINDOWS ! flush register windows
285 retl ! return from leaf routine