0.7.4.19:
[sbcl.git] / src / runtime / sparc-assem.S
1 #define _ASM
2
3 #define FUNCDEF(x)      .type x,@function
4
5 #define LANGUAGE_ASSEMBLY
6 #include "lispregs.h"
7 #include "globals.h"
8 #include "sbcl.h"
9
10
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)]
15
16 /* FIXME */
17 #define FRAMESIZE 0x48
18 #define ST_FLUSH_WINDOWS 0x03
19         .seg    "text"
20         .global call_into_lisp
21         FUNCDEF(call_into_lisp)
22 call_into_lisp:
23         save    %sp, -FRAMESIZE, %sp
24
25         /* Flush all of C's register windows to the stack. */
26         ta      ST_FLUSH_WINDOWS
27
28         /* Save the return address. */
29         st      %i7, [%fp-4]
30
31         /* Clear the descriptor regs. (See sparc/vm.lisp) */
32         mov     reg_ZERO, reg_A0
33         mov     reg_ZERO, reg_A1
34         mov     reg_ZERO, reg_A2
35         mov     reg_ZERO, reg_A3
36         mov     reg_ZERO, reg_A4
37         mov     reg_ZERO, reg_A5
38         mov     reg_ZERO, reg_OCFP
39         mov     reg_ZERO, reg_LRA
40         mov     reg_ZERO, reg_CODE
41
42         /* Establish NIL */
43         set     NIL, reg_NIL
44
45         /* Set the pseudo-atomic flag. */
46         set     4, reg_ALLOC
47
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)]
51
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)
58
59         /* No longer atomic, and check for interrupt. */
60         sub     reg_ALLOC, 4, reg_ALLOC
61         andcc   reg_ALLOC, 3, reg_ZERO
62         
63         tne     PSEUDO_ATOMIC_TRAP
64         /* Pass in the args. */
65         sll     %i2, 2, reg_NARGS
66         mov     %i1, reg_CFP
67         mov     %i0, reg_LEXENV
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
74
75         /* Calculate LRA */
76         set     lra + OTHER_POINTER_LOWTAG, reg_LRA
77
78         /* Indirect closure */
79         ld      [reg_LEXENV+CLOSURE_FUN_OFFSET], reg_CODE
80
81         jmp     reg_CODE+SIMPLE_FUN_CODE_OFFSET
82         nop
83
84         .align  8
85 lra:
86         .word   RETURN_PC_HEADER_WIDETAG
87
88         /* Blow off any extra values. */
89         mov     reg_OCFP, reg_CSP
90         nop
91
92         /* Return the one value. */
93         mov     reg_A0, %i0
94
95         /* Turn on pseudo_atomic */
96         add     reg_ALLOC, 4, reg_ALLOC
97
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)
104
105         /* No longer in Lisp. */
106         store(reg_NL1,foreign_function_call_active)
107
108         /* Were we interrupted? */
109         sub     reg_ALLOC, 4, reg_ALLOC
110         andcc   reg_ALLOC, 3, reg_ZERO
111         tne     PSEUDO_ATOMIC_TRAP
112
113         /* Back to C we go. */
114         ld      [%sp+FRAMESIZE-4], %i7
115         ret
116         restore %sp, FRAMESIZE, %sp
117
118         .global call_into_c
119         FUNCDEF(call_into_c)
120 call_into_c:
121         /* Build a lisp stack frame */
122         mov     reg_CFP, reg_OCFP
123         mov     reg_CSP, reg_CFP
124         add     reg_CSP, 32, reg_CSP
125         st      reg_OCFP, [reg_CFP]
126         st      reg_CODE, [reg_CFP+8]
127
128         /* Turn on pseudo-atomic. */
129         add     reg_ALLOC, 4, reg_ALLOC
130
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]
135
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)
144
145         /* No longer in Lisp. */
146         store(reg_CSP,foreign_function_call_active)
147
148         /* Were we interrupted? */
149         sub     reg_ALLOC, 4, reg_ALLOC
150         andcc   reg_ALLOC, 3, reg_ZERO
151         tne     PSEUDO_ATOMIC_TRAP
152
153         /* Into C we go. */
154         call    reg_CFUNC
155         nop
156
157         /*
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).  
161          */
162         
163         /* Re-establish NIL */
164         set     NIL, reg_NIL
165
166         /* Atomic. */
167         set     4, reg_ALLOC
168
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)]
172
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)
179
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
185
186         /* No longer atomic. */
187         sub     reg_ALLOC, 4, reg_ALLOC
188         andcc   reg_ALLOC, 3, reg_ZERO
189         tne     PSEUDO_ATOMIC_TRAP
190
191         /* Reset the lisp stack. */
192         /* Note: OCFP is in one of the locals, it gets preserved across C. */
193         mov     reg_CFP, reg_CSP
194         mov     reg_OCFP, reg_CFP
195
196         /* And back into lisp. */
197         ret
198         nop
199
200         .global undefined_tramp
201         FUNCDEF(undefined_tramp)
202         .align  8
203         .byte   0, 0, 0, SIMPLE_FUN_HEADER_WIDETAG
204 undefined_tramp = . + 1
205         .word   undefined_tramp
206         .word   NIL
207         .word   NIL
208         .word   NIL
209         .word   NIL
210
211         b       1f
212         unimp   trap_Cerror
213         .byte   4
214         .byte   UNDEFINED_FUN_ERROR
215         .byte   254, sc_DescriptorReg, 3
216         .align  4
217 1:
218         ld      [reg_FDEFN+FDEFN_RAW_ADDR_OFFSET], reg_CODE
219         jmp     reg_CODE+SIMPLE_FUN_CODE_OFFSET
220         nop
221
222         .global closure_tramp
223         FUNCDEF(closure_tramp)
224         .align  8
225         .byte   0, 0, 0, SIMPLE_FUN_HEADER_WIDETAG
226 closure_tramp = . + 1
227         .word   closure_tramp
228         .word   NIL
229         .word   NIL
230         .word   NIL
231         .word   NIL
232
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
236         nop
237
238
239 /*
240  * Function-end breakpoint magic.
241  */
242
243         .text
244         .align  8
245         .global fun_end_breakpoint_guts
246 fun_end_breakpoint_guts:
247         .word   RETURN_PC_HEADER_WIDETAG
248         b       1f
249         nop
250         mov     reg_CSP, reg_OCFP
251         add     4, reg_CSP, reg_CSP
252         mov     4, reg_NARGS
253         mov     reg_NIL, reg_A1
254         mov     reg_NIL, reg_A2
255         mov     reg_NIL, reg_A3
256         mov     reg_NIL, reg_A4
257         mov     reg_NIL, reg_A5
258 1:
259
260         .global fun_end_breakpoint_trap
261 fun_end_breakpoint_trap:
262         unimp   trap_FunEndBreakpoint
263         b       1b
264         nop
265
266         .global fun_end_breakpoint_end
267 fun_end_breakpoint_end:
268
269         .global sparc_flush_icache
270         FUNCDEF(sparc_flush_icache)
271 sparc_flush_icache:
272         add %o0,%o1,%o2
273 1:      iflush %o0                      ! flush instruction cache
274         add %o0,8,%o0
275         cmp %o0,%o2
276         blt 1b
277         nop
278         retl                            ! return from leaf routine
279         nop
280
281         .global save_context
282         FUNCDEF(save_context)
283 save_context:
284         ta      ST_FLUSH_WINDOWS        ! flush register windows
285         retl                            ! return from leaf routine
286         nop 
287