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
19 #define PSEUDO_ATOMIC_TRAP_NUMBER 64
21 .global call_into_lisp
22 FUNCDEF(call_into_lisp)
24 save %sp, -FRAMESIZE, %sp
26 /* Flush all of C's register windows to the stack. */
29 /* Save the return address. */
32 /* Clear the descriptor regs. (See sparc/vm.lisp) */
39 mov reg_ZERO, reg_OCFP
41 mov reg_ZERO, reg_CODE
46 /* Set the pseudo-atomic flag. */
49 /* Turn off foreign function call. */
50 sethi %hi(foreign_function_call_active), reg_NL0
51 st reg_ZERO, [reg_NL0+%lo(foreign_function_call_active)]
53 /* Load the rest of lisp state. */
54 load(dynamic_space_free_pointer, reg_NL0)
55 add reg_NL0, reg_ALLOC, reg_ALLOC
56 load(current_binding_stack_pointer, reg_BSP)
57 load(current_control_stack_pointer, reg_CSP)
58 load(current_control_frame_pointer, reg_OCFP)
60 /* No longer atomic, and check for interrupt. */
61 sub reg_ALLOC, 4, reg_ALLOC
62 andcc reg_ALLOC, 3, reg_ZERO
64 /* OK, this is ridiculous. We badly urgently need this to be
65 centralized, because that's now _three_ places where this
66 number is used. CSR, 2002-02-09 */
69 /* Pass in the args. */
73 ld [reg_CFP+0], reg_A0
74 ld [reg_CFP+4], reg_A1
75 ld [reg_CFP+8], reg_A2
76 ld [reg_CFP+12], reg_A3
77 ld [reg_CFP+16], reg_A4
78 ld [reg_CFP+20], reg_A5
81 set lra + OTHER_POINTER_LOWTAG, reg_LRA
83 /* Indirect closure */
84 ld [reg_LEXENV+CLOSURE_FUN_OFFSET], reg_CODE
86 jmp reg_CODE+SIMPLE_FUN_CODE_OFFSET
91 .word RETURN_PC_HEADER_WIDETAG
93 /* Blow off any extra values. */
97 /* Return the one value. */
100 /* Turn on pseudo_atomic */
101 add reg_ALLOC, 4, reg_ALLOC
103 /* Store LISP state */
104 andn reg_ALLOC, 7, reg_NL1
105 store(reg_NL1,dynamic_space_free_pointer)
106 store(reg_BSP,current_binding_stack_pointer)
107 store(reg_CSP,current_control_stack_pointer)
108 store(reg_CFP,current_control_frame_pointer)
110 /* No longer in Lisp. */
111 store(reg_NL1,foreign_function_call_active)
113 /* Were we interrupted? */
114 sub reg_ALLOC, 4, reg_ALLOC
115 andcc reg_ALLOC, 3, reg_ZERO
116 tne PSEUDO_ATOMIC_TRAP_NUMBER
118 /* Back to C we go. */
119 ld [%sp+FRAMESIZE-4], %i7
121 restore %sp, FRAMESIZE, %sp
126 /* Build a lisp stack frame */
127 mov reg_CFP, reg_OCFP
129 add reg_CSP, 32, reg_CSP
130 st reg_OCFP, [reg_CFP]
131 st reg_CODE, [reg_CFP+8]
133 /* Turn on pseudo-atomic. */
134 add reg_ALLOC, 4, reg_ALLOC
136 /* Convert the return address to an offset and save it on the stack. */
137 sub reg_LIP, reg_CODE, reg_L0
138 add reg_L0, OTHER_POINTER_LOWTAG, reg_L0
139 st reg_L0, [reg_CFP+4]
141 /* Store LISP state */
142 store(reg_BSP,current_binding_stack_pointer)
143 store(reg_CSP,current_control_stack_pointer)
144 store(reg_CFP,current_control_frame_pointer)
145 /* Use reg_CFP as a work register, and restore it */
146 andn reg_ALLOC, 7, reg_CFP
147 store(reg_CFP,dynamic_space_free_pointer)
148 load(current_control_frame_pointer, reg_CFP)
150 /* No longer in Lisp. */
151 store(reg_CSP,foreign_function_call_active)
153 /* Were we interrupted? */
154 sub reg_ALLOC, 4, reg_ALLOC
155 andcc reg_ALLOC, 3, reg_ZERO
156 tne PSEUDO_ATOMIC_TRAP_NUMBER
163 * Note: C calling conventions (32-bit) say that %o0 and %o1
164 * are used to return function results. In particular 64-bit
165 * results are in %o0 (hi) and %o1 (low).
168 /* Re-establish NIL */
174 /* No longer in foreign function call. */
175 sethi %hi(foreign_function_call_active), reg_NL2
176 st reg_ZERO, [reg_NL2+%lo(foreign_function_call_active)]
178 /* Load the rest of lisp state. */
179 load(dynamic_space_free_pointer, reg_NL2)
180 add reg_NL2, reg_ALLOC, reg_ALLOC
181 load(current_binding_stack_pointer, reg_BSP)
182 load(current_control_stack_pointer, reg_CSP)
183 load(current_control_frame_pointer, reg_CFP)
185 /* Get the return address back. */
186 ld [reg_CFP+4], reg_LIP
187 ld [reg_CFP+8], reg_CODE
188 add reg_LIP, reg_CODE, reg_LIP
189 sub reg_LIP, OTHER_POINTER_LOWTAG, reg_LIP
191 /* No longer atomic. */
192 sub reg_ALLOC, 4, reg_ALLOC
193 andcc reg_ALLOC, 3, reg_ZERO
194 tne PSEUDO_ATOMIC_TRAP_NUMBER
196 /* Reset the lisp stack. */
197 /* Note: OCFP is in one of the locals, it gets preserved across C. */
199 mov reg_OCFP, reg_CFP
201 /* And back into lisp. */
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 #ifdef type_LongFloat
224 .byte 254, sc_DescriptorReg, 3
227 ld [reg_FDEFN+FDEFN_RAW_ADDR_OFFSET], reg_CODE
228 jmp reg_CODE+SIMPLE_FUN_CODE_OFFSET
231 .global closure_tramp
232 FUNCDEF(closure_tramp)
234 .byte 0, 0, 0, SIMPLE_FUN_HEADER_WIDETAG
235 closure_tramp = . + 1
242 ld [reg_FDEFN+FDEFN_FUN_OFFSET], reg_LEXENV
243 ld [reg_LEXENV+CLOSURE_FUN_OFFSET], reg_CODE
244 jmp reg_CODE+SIMPLE_FUN_CODE_OFFSET
249 * Function-end breakpoint magic.
254 .global fun_end_breakpoint_guts
255 fun_end_breakpoint_guts:
256 .word RETURN_PC_HEADER_WIDETAG
259 mov reg_CSP, reg_OCFP
260 add 4, reg_CSP, reg_CSP
269 .global fun_end_breakpoint_trap
270 fun_end_breakpoint_trap:
271 unimp trap_FunEndBreakpoint
275 .global fun_end_breakpoint_end
276 fun_end_breakpoint_end:
279 FUNCDEF(flush_icache)
282 1: iflush %o0 ! flush instruction cache
287 retl ! return from leaf routine
291 FUNCDEF(save_context)
293 ta ST_FLUSH_WINDOWS ! flush register windows
294 retl ! return from leaf routine