Change immobile space free pointers to alien vars
[sbcl.git] / src / runtime / sparc-assem.S
blob0ffe70465803e5bf8e0052834caac1dfcc7b2156
1 #ifdef __ELF__
2 // Mark the object as not requiring an executable stack.
3 .section .note.GNU-stack,"",%progbits
4 #endif
6 #define _ASM
8 #include "sparc-funcdef.h"
10 #define LANGUAGE_ASSEMBLY
11 #include "lispregs.h"
12 #include "globals.h"
13 #include "sbcl.h"
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)]
25 /* FIXME */
26 #define FRAMESIZE 0x48
27 #define ST_FLUSH_WINDOWS 0x03
28         .seg    "text"
29         .global call_into_lisp
30         FUNCDEF(call_into_lisp)
31 call_into_lisp:
32         save    %sp, -FRAMESIZE, %sp
34         /* Flush all of C's register windows to the stack. */
35         ta      ST_FLUSH_WINDOWS
37         /* Save the return address. */
38         st      %i7, [%fp-4]
40         /* Clear the descriptor regs. (See sparc/vm.lisp) */
41         mov     reg_ZERO, reg_A0
42         mov     reg_ZERO, reg_A1
43         mov     reg_ZERO, reg_A2
44         mov     reg_ZERO, reg_A3
45         mov     reg_ZERO, reg_A4
46         mov     reg_ZERO, reg_A5
47         mov     reg_ZERO, reg_OCFP
48         mov     reg_ZERO, reg_LRA
49         mov     reg_ZERO, reg_CODE
51         /* Establish NIL */
52         set     NIL, reg_NIL
54         /* Set the pseudo-atomic flag. */
55         set     4, reg_ALLOC
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
71         
72         tne     PSEUDO_ATOMIC_TRAP
73         /* Pass in the args. */
74         sll     %i2, 2, reg_NARGS
75         mov     %i1, reg_CFP
76         mov     %i0, reg_LEXENV
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
84         /* Calculate LRA */
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
91         nop
93         .align  8
94 lra:
95         .word   RETURN_PC_WIDETAG
97         /* Blow off any extra values. */
98         mov     reg_OCFP, reg_CSP
99         nop
101         /* Return the one value. */
102         mov     reg_A0, %i0
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
124         ret
125         restore %sp, FRAMESIZE, %sp
127         .global call_into_c
128         FUNCDEF(call_into_c)
129 call_into_c:
130         /* Build a lisp stack frame */
131         mov     reg_CFP, reg_OCFP
132         mov     reg_CSP, reg_CFP
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
162         /* Into C we go. */
163         call    reg_CFUNC
164         nop
166         /*
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).  
170          */
171         
172         /* Re-establish NIL */
173         set     NIL, reg_NIL
175         /* Atomic. */
176         set     4, reg_ALLOC
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. */
202         mov     reg_CFP, reg_CSP
203         mov     reg_OCFP, reg_CFP
205         /* And back into lisp. */
206         ret
207         nop
210  * Function-end breakpoint magic.
211  */
214  * For an explanation of the magic involved in function-end
215  * breakpoints, see the implementation in ppc-assem.S.
216  */
218         .text
219         .align  8
220         .global fun_end_breakpoint_guts
221 fun_end_breakpoint_guts:
222         .word   RETURN_PC_WIDETAG + 0x600
223         b       1f
224         nop
225         mov     reg_CSP, reg_OCFP
226         add     4, reg_CSP, reg_CSP
227         mov     4, reg_NARGS
228         mov     reg_NIL, reg_A1
229         mov     reg_NIL, reg_A2
230         mov     reg_NIL, reg_A3
231         mov     reg_NIL, reg_A4
232         mov     reg_NIL, reg_A5
235         .global fun_end_breakpoint_trap
236 fun_end_breakpoint_trap:
237         unimp   trap_FunEndBreakpoint
238         b       1b
239         nop
241         .global fun_end_breakpoint_end
242 fun_end_breakpoint_end:
244         .global sparc_flush_icache
245         FUNCDEF(sparc_flush_icache)
246 sparc_flush_icache:
247         add %o0,%o1,%o2
248 1:      iflush %o0                      ! flush instruction cache
249         add %o0,8,%o0
250         cmp %o0,%o2
251         blt 1b
252         nop
253         retl                            ! return from leaf routine
254         nop
256         .global do_pending_interrupt
257         FUNCDEF(do_pending_interrupt)
258 do_pending_interrupt:
259         unimp   trap_PendingInterrupt
260         retl
261         nop
263         .global save_context
264         FUNCDEF(save_context)
265 save_context:
266         ta      ST_FLUSH_WINDOWS        ! flush register windows
267         retl                            ! return from leaf routine
268         nop