0.7.13.9:
[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 #include "genesis/closure.h"
10 #include "genesis/fdefn.h"
11 #include "genesis/static-symbols.h"
12 #include "genesis/simple-fun.h" 
13
14 #define load(sym, reg) \
15         sethi %hi(sym), reg; ld [reg+%lo(sym)], reg
16 #define store(reg, sym) \
17         sethi %hi(sym), reg_L0; st reg, [reg_L0+%lo(sym)]
18
19 /* FIXME */
20 #define FRAMESIZE 0x48
21 #define ST_FLUSH_WINDOWS 0x03
22         .seg    "text"
23         .global call_into_lisp
24         FUNCDEF(call_into_lisp)
25 call_into_lisp:
26         save    %sp, -FRAMESIZE, %sp
27
28         /* Flush all of C's register windows to the stack. */
29         ta      ST_FLUSH_WINDOWS
30
31         /* Save the return address. */
32         st      %i7, [%fp-4]
33
34         /* Clear the descriptor regs. (See sparc/vm.lisp) */
35         mov     reg_ZERO, reg_A0
36         mov     reg_ZERO, reg_A1
37         mov     reg_ZERO, reg_A2
38         mov     reg_ZERO, reg_A3
39         mov     reg_ZERO, reg_A4
40         mov     reg_ZERO, reg_A5
41         mov     reg_ZERO, reg_OCFP
42         mov     reg_ZERO, reg_LRA
43         mov     reg_ZERO, reg_CODE
44
45         /* Establish NIL */
46         set     NIL, reg_NIL
47
48         /* Set the pseudo-atomic flag. */
49         set     4, reg_ALLOC
50
51         /* Turn off foreign function call. */
52         sethi   %hi(foreign_function_call_active), reg_NL0
53         st      reg_ZERO, [reg_NL0+%lo(foreign_function_call_active)]
54
55         /* Load the rest of lisp state. */
56         load(dynamic_space_free_pointer, reg_NL0)
57         add     reg_NL0, reg_ALLOC, reg_ALLOC
58         load(current_binding_stack_pointer, reg_BSP)
59         load(current_control_stack_pointer, reg_CSP)
60         load(current_control_frame_pointer, reg_OCFP)
61
62         /* No longer atomic, and check for interrupt. */
63         sub     reg_ALLOC, 4, reg_ALLOC
64         andcc   reg_ALLOC, 3, reg_ZERO
65         
66         tne     PSEUDO_ATOMIC_TRAP
67         /* Pass in the args. */
68         sll     %i2, 2, reg_NARGS
69         mov     %i1, reg_CFP
70         mov     %i0, reg_LEXENV
71         ld      [reg_CFP+0], reg_A0
72         ld      [reg_CFP+4], reg_A1
73         ld      [reg_CFP+8], reg_A2
74         ld      [reg_CFP+12], reg_A3
75         ld      [reg_CFP+16], reg_A4
76         ld      [reg_CFP+20], reg_A5
77
78         /* Calculate LRA */
79         set     lra + OTHER_POINTER_LOWTAG, reg_LRA
80
81         /* Indirect closure */
82         ld      [reg_LEXENV+CLOSURE_FUN_OFFSET], reg_CODE
83
84         jmp     reg_CODE+SIMPLE_FUN_CODE_OFFSET
85         nop
86
87         .align  8
88 lra:
89         .word   RETURN_PC_HEADER_WIDETAG
90
91         /* Blow off any extra values. */
92         mov     reg_OCFP, reg_CSP
93         nop
94
95         /* Return the one value. */
96         mov     reg_A0, %i0
97
98         /* Turn on pseudo_atomic */
99         add     reg_ALLOC, 4, reg_ALLOC
100
101         /* Store LISP state */
102         andn    reg_ALLOC, 7, reg_NL1
103         store(reg_NL1,dynamic_space_free_pointer)
104         store(reg_BSP,current_binding_stack_pointer)
105         store(reg_CSP,current_control_stack_pointer)
106         store(reg_CFP,current_control_frame_pointer)
107
108         /* No longer in Lisp. */
109         store(reg_NL1,foreign_function_call_active)
110
111         /* Were we interrupted? */
112         sub     reg_ALLOC, 4, reg_ALLOC
113         andcc   reg_ALLOC, 3, reg_ZERO
114         tne     PSEUDO_ATOMIC_TRAP
115
116         /* Back to C we go. */
117         ld      [%sp+FRAMESIZE-4], %i7
118         ret
119         restore %sp, FRAMESIZE, %sp
120
121         .global call_into_c
122         FUNCDEF(call_into_c)
123 call_into_c:
124         /* Build a lisp stack frame */
125         mov     reg_CFP, reg_OCFP
126         mov     reg_CSP, reg_CFP
127         add     reg_CSP, 32, reg_CSP
128         st      reg_OCFP, [reg_CFP]
129         st      reg_CODE, [reg_CFP+8]
130
131         /* Turn on pseudo-atomic. */
132         add     reg_ALLOC, 4, reg_ALLOC
133
134         /* Convert the return address to an offset and save it on the stack. */
135         sub     reg_LIP, reg_CODE, reg_L0
136         add     reg_L0, OTHER_POINTER_LOWTAG, reg_L0
137         st      reg_L0, [reg_CFP+4]
138
139         /* Store LISP state */
140         store(reg_BSP,current_binding_stack_pointer)
141         store(reg_CSP,current_control_stack_pointer)
142         store(reg_CFP,current_control_frame_pointer)
143         /* Use reg_CFP as a work register, and restore it */
144         andn    reg_ALLOC, 7, reg_CFP
145         store(reg_CFP,dynamic_space_free_pointer)
146                 load(current_control_frame_pointer, reg_CFP)
147
148         /* No longer in Lisp. */
149         store(reg_CSP,foreign_function_call_active)
150
151         /* Were we interrupted? */
152         sub     reg_ALLOC, 4, reg_ALLOC
153         andcc   reg_ALLOC, 3, reg_ZERO
154         tne     PSEUDO_ATOMIC_TRAP
155
156         /* Into C we go. */
157         call    reg_CFUNC
158         nop
159
160         /*
161          * Note: C calling conventions (32-bit) say that %o0 and %o1
162          * are used to return function results.  In particular 64-bit
163          * results are in %o0 (hi) and %o1 (low).  
164          */
165         
166         /* Re-establish NIL */
167         set     NIL, reg_NIL
168
169         /* Atomic. */
170         set     4, reg_ALLOC
171
172         /* No longer in foreign function call. */
173         sethi   %hi(foreign_function_call_active), reg_NL2
174         st      reg_ZERO, [reg_NL2+%lo(foreign_function_call_active)]
175
176         /* Load the rest of lisp state. */
177         load(dynamic_space_free_pointer, reg_NL2)
178         add     reg_NL2, reg_ALLOC, reg_ALLOC
179         load(current_binding_stack_pointer, reg_BSP)
180         load(current_control_stack_pointer, reg_CSP)
181         load(current_control_frame_pointer, reg_CFP)
182
183         /* Get the return address back. */
184         ld      [reg_CFP+4], reg_LIP
185         ld      [reg_CFP+8], reg_CODE
186         add     reg_LIP, reg_CODE, reg_LIP
187         sub     reg_LIP, OTHER_POINTER_LOWTAG, reg_LIP
188
189         /* No longer atomic. */
190         sub     reg_ALLOC, 4, reg_ALLOC
191         andcc   reg_ALLOC, 3, reg_ZERO
192         tne     PSEUDO_ATOMIC_TRAP
193
194         /* Reset the lisp stack. */
195         /* Note: OCFP is in one of the locals, it gets preserved across C. */
196         mov     reg_CFP, reg_CSP
197         mov     reg_OCFP, reg_CFP
198
199         /* And back into lisp. */
200         ret
201         nop
202
203         .global undefined_tramp
204         FUNCDEF(undefined_tramp)
205         .align  8
206         .byte   0, 0, 0, SIMPLE_FUN_HEADER_WIDETAG
207 undefined_tramp = . + 1
208         .word   undefined_tramp
209         .word   NIL
210         .word   NIL
211         .word   NIL
212         .word   NIL
213
214         b       1f
215         unimp   trap_Cerror
216         .byte   4
217         .byte   UNDEFINED_FUN_ERROR
218         .byte   254, sc_DescriptorReg, 3
219         .align  4
220 1:
221         ld      [reg_FDEFN+FDEFN_RAW_ADDR_OFFSET], reg_CODE
222         jmp     reg_CODE+SIMPLE_FUN_CODE_OFFSET
223         nop
224
225         .global closure_tramp
226         FUNCDEF(closure_tramp)
227         .align  8
228         .byte   0, 0, 0, SIMPLE_FUN_HEADER_WIDETAG
229 closure_tramp = . + 1
230         .word   closure_tramp
231         .word   NIL
232         .word   NIL
233         .word   NIL
234         .word   NIL
235
236         ld      [reg_FDEFN+FDEFN_FUN_OFFSET], reg_LEXENV
237         ld      [reg_LEXENV+CLOSURE_FUN_OFFSET], reg_CODE
238         jmp     reg_CODE+SIMPLE_FUN_CODE_OFFSET
239         nop
240
241
242 /*
243  * Function-end breakpoint magic.
244  */
245
246         .text
247         .align  8
248         .global fun_end_breakpoint_guts
249 fun_end_breakpoint_guts:
250         .word   RETURN_PC_HEADER_WIDETAG
251         b       1f
252         nop
253         mov     reg_CSP, reg_OCFP
254         add     4, reg_CSP, reg_CSP
255         mov     4, reg_NARGS
256         mov     reg_NIL, reg_A1
257         mov     reg_NIL, reg_A2
258         mov     reg_NIL, reg_A3
259         mov     reg_NIL, reg_A4
260         mov     reg_NIL, reg_A5
261 1:
262
263         .global fun_end_breakpoint_trap
264 fun_end_breakpoint_trap:
265         unimp   trap_FunEndBreakpoint
266         b       1b
267         nop
268
269         .global fun_end_breakpoint_end
270 fun_end_breakpoint_end:
271
272         .global sparc_flush_icache
273         FUNCDEF(sparc_flush_icache)
274 sparc_flush_icache:
275         add %o0,%o1,%o2
276 1:      iflush %o0                      ! flush instruction cache
277         add %o0,8,%o0
278         cmp %o0,%o2
279         blt 1b
280         nop
281         retl                            ! return from leaf routine
282         nop
283
284         .global save_context
285         FUNCDEF(save_context)
286 save_context:
287         ta      ST_FLUSH_WINDOWS        ! flush register windows
288         retl                            ! return from leaf routine
289         nop 
290