0.7.1.20:
[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 #define PSEUDO_ATOMIC_TRAP_NUMBER 64
20         .seg    "text"
21         .global call_into_lisp
22         FUNCDEF(call_into_lisp)
23 call_into_lisp:
24         save    %sp, -FRAMESIZE, %sp
25
26         /* Flush all of C's register windows to the stack. */
27         ta      ST_FLUSH_WINDOWS
28
29         /* Save the return address. */
30         st      %i7, [%fp-4]
31
32         /* Clear the descriptor regs. (See sparc/vm.lisp) */
33         mov     reg_ZERO, reg_A0
34         mov     reg_ZERO, reg_A1
35         mov     reg_ZERO, reg_A2
36         mov     reg_ZERO, reg_A3
37         mov     reg_ZERO, reg_A4
38         mov     reg_ZERO, reg_A5
39         mov     reg_ZERO, reg_OCFP
40         mov     reg_ZERO, reg_LRA
41         mov     reg_ZERO, reg_CODE
42
43         /* Establish NIL */
44         set     NIL, reg_NIL
45
46         /* Set the pseudo-atomic flag. */
47         set     4, reg_ALLOC
48
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)]
52
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)
59
60         /* No longer atomic, and check for interrupt. */
61         sub     reg_ALLOC, 4, reg_ALLOC
62         andcc   reg_ALLOC, 3, reg_ZERO
63         
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 */
67
68         tne     64
69         /* Pass in the args. */
70         sll     %i2, 2, reg_NARGS
71         mov     %i1, reg_CFP
72         mov     %i0, reg_LEXENV
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
79
80         /* Calculate LRA */
81         set     lra + OTHER_POINTER_LOWTAG, reg_LRA
82
83         /* Indirect closure */
84         ld      [reg_LEXENV+CLOSURE_FUN_OFFSET], reg_CODE
85
86         jmp     reg_CODE+SIMPLE_FUN_CODE_OFFSET
87         nop
88
89         .align  8
90 lra:
91         .word   RETURN_PC_HEADER_WIDETAG
92
93         /* Blow off any extra values. */
94         mov     reg_OCFP, reg_CSP
95         nop
96
97         /* Return the one value. */
98         mov     reg_A0, %i0
99
100         /* Turn on pseudo_atomic */
101         add     reg_ALLOC, 4, reg_ALLOC
102
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)
109
110         /* No longer in Lisp. */
111         store(reg_NL1,foreign_function_call_active)
112
113         /* Were we interrupted? */
114         sub     reg_ALLOC, 4, reg_ALLOC
115         andcc   reg_ALLOC, 3, reg_ZERO
116         tne     PSEUDO_ATOMIC_TRAP_NUMBER
117
118         /* Back to C we go. */
119         ld      [%sp+FRAMESIZE-4], %i7
120         ret
121         restore %sp, FRAMESIZE, %sp
122
123         .global call_into_c
124         FUNCDEF(call_into_c)
125 call_into_c:
126         /* Build a lisp stack frame */
127         mov     reg_CFP, reg_OCFP
128         mov     reg_CSP, reg_CFP
129         add     reg_CSP, 32, reg_CSP
130         st      reg_OCFP, [reg_CFP]
131         st      reg_CODE, [reg_CFP+8]
132
133         /* Turn on pseudo-atomic. */
134         add     reg_ALLOC, 4, reg_ALLOC
135
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]
140
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)
149
150         /* No longer in Lisp. */
151         store(reg_CSP,foreign_function_call_active)
152
153         /* Were we interrupted? */
154         sub     reg_ALLOC, 4, reg_ALLOC
155         andcc   reg_ALLOC, 3, reg_ZERO
156         tne     PSEUDO_ATOMIC_TRAP_NUMBER
157
158         /* Into C we go. */
159         call    reg_CFUNC
160         nop
161
162         /*
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).  
166          */
167         
168         /* Re-establish NIL */
169         set     NIL, reg_NIL
170
171         /* Atomic. */
172         set     4, reg_ALLOC
173
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)]
177
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)
184
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
190
191         /* No longer atomic. */
192         sub     reg_ALLOC, 4, reg_ALLOC
193         andcc   reg_ALLOC, 3, reg_ZERO
194         tne     PSEUDO_ATOMIC_TRAP_NUMBER
195
196         /* Reset the lisp stack. */
197         /* Note: OCFP is in one of the locals, it gets preserved across C. */
198         mov     reg_CFP, reg_CSP
199         mov     reg_OCFP, reg_CFP
200
201         /* And back into lisp. */
202         ret
203         nop
204
205         .global undefined_tramp
206         FUNCDEF(undefined_tramp)
207         .align  8
208         .byte   0, 0, 0, SIMPLE_FUN_HEADER_WIDETAG
209 undefined_tramp = . + 1
210         .word   undefined_tramp
211         .word   NIL
212         .word   NIL
213         .word   NIL
214         .word   NIL
215
216         b       1f
217         unimp   trap_Cerror
218         .byte   4
219 #ifdef type_LongFloat
220         .byte   24
221 #else
222         .byte   23
223 #endif
224         .byte   254, sc_DescriptorReg, 3
225         .align  4
226 1:
227         ld      [reg_FDEFN+FDEFN_RAW_ADDR_OFFSET], reg_CODE
228         jmp     reg_CODE+SIMPLE_FUN_CODE_OFFSET
229         nop
230
231         .global closure_tramp
232         FUNCDEF(closure_tramp)
233         .align  8
234         .byte   0, 0, 0, SIMPLE_FUN_HEADER_WIDETAG
235 closure_tramp = . + 1
236         .word   closure_tramp
237         .word   NIL
238         .word   NIL
239         .word   NIL
240         .word   NIL
241
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
245         nop
246
247
248 /*
249  * Function-end breakpoint magic.
250  */
251
252         .text
253         .align  8
254         .global fun_end_breakpoint_guts
255 fun_end_breakpoint_guts:
256         .word   RETURN_PC_HEADER_WIDETAG
257         b       1f
258         nop
259         mov     reg_CSP, reg_OCFP
260         add     4, reg_CSP, reg_CSP
261         mov     4, reg_NARGS
262         mov     reg_NIL, reg_A1
263         mov     reg_NIL, reg_A2
264         mov     reg_NIL, reg_A3
265         mov     reg_NIL, reg_A4
266         mov     reg_NIL, reg_A5
267 1:
268
269         .global fun_end_breakpoint_trap
270 fun_end_breakpoint_trap:
271         unimp   trap_FunEndBreakpoint
272         b       1b
273         nop
274
275         .global fun_end_breakpoint_end
276 fun_end_breakpoint_end:
277
278         .global flush_icache
279         FUNCDEF(flush_icache)
280 flush_icache:
281         add %o0,%o1,%o2
282 1:      iflush %o0                      ! flush instruction cache
283         add %o0,8,%o0
284         cmp %o0,%o2
285         blt 1b
286         nop
287         retl                            ! return from leaf routine
288         nop
289
290         .global save_context
291         FUNCDEF(save_context)
292 save_context:
293         ta      ST_FLUSH_WINDOWS        ! flush register windows
294         retl                            ! return from leaf routine
295         nop