* Added Array.{map2,fold_left2,fold_right2} (from stdlib2)
[ocaml.git] / asmrun / sparc.S
blob38d0be0c16a5e1e7de0d08d72badc07b54f1b124
1 /***********************************************************************/
2 /*                                                                     */
3 /*                           Objective Caml                            */
4 /*                                                                     */
5 /*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         */
6 /*                                                                     */
7 /*  Copyright 1996 Institut National de Recherche en Informatique et   */
8 /*  en Automatique.  All rights reserved.  This file is distributed    */
9 /*  under the terms of the GNU Library General Public License, with    */
10 /*  the special exception on linking described in file ../LICENSE.     */
11 /*                                                                     */
12 /***********************************************************************/
14 /* $Id$ */
16 /* Asm part of the runtime system for the Sparc processor.  */
17 /* Must be preprocessed by cpp */
19 /* SunOS 4 prefixes identifiers with _ */
21 #if defined(SYS_sunos)
23 #define Caml_young_limit _caml_young_limit
24 #define Caml_young_ptr _caml_young_ptr
25 #define Caml_bottom_of_stack _caml_bottom_of_stack
26 #define Caml_last_return_address _caml_last_return_address
27 #define Caml_gc_regs _caml_gc_regs
28 #define Caml_exception_pointer _caml_exception_pointer
29 #define Caml_allocN _caml_allocN
30 #define Caml_call_gc _caml_call_gc
31 #define Caml_garbage_collection _caml_garbage_collection
32 #define Caml_c_call _caml_c_call
33 #define Caml_start_program _caml_start_program
34 #define Caml_program _caml_program
35 #define Caml_raise_exception _caml_raise_exception
36 #define Caml_callback_exn _caml_callback_exn
37 #define Caml_callback2_exn _caml_callback2_exn
38 #define Caml_callback3_exn _caml_callback3_exn
39 #define Caml_apply2 _caml_apply2
40 #define Caml_apply3 _caml_apply3
41 #define Caml_raise _caml_raise
42 #define Caml_system__frametable _caml_system__frametable
43 #define Caml_ml_array_bound_error _caml_ml_array_bound_error
44 #define Caml_array_bound_error _caml_array_bound_error
46 #else
48 #define Caml_young_limit caml_young_limit
49 #define Caml_young_ptr caml_young_ptr
50 #define Caml_bottom_of_stack caml_bottom_of_stack
51 #define Caml_last_return_address caml_last_return_address
52 #define Caml_gc_regs caml_gc_regs
53 #define Caml_exception_pointer caml_exception_pointer
54 #define Caml_allocN caml_allocN
55 #define Caml_call_gc caml_call_gc
56 #define Caml_garbage_collection caml_garbage_collection
57 #define Caml_c_call caml_c_call
58 #define Caml_start_program caml_start_program
59 #define Caml_program caml_program
60 #define Caml_raise_exception caml_raise_exception
61 #define Caml_callback_exn caml_callback_exn
62 #define Caml_callback2_exn caml_callback2_exn
63 #define Caml_callback3_exn caml_callback3_exn
64 #define Caml_apply2 caml_apply2
65 #define Caml_apply3 caml_apply3
66 #define Caml_raise caml_raise
67 #define Caml_system__frametable caml_system__frametable
68 #define Caml_ml_array_bound_error caml_ml_array_bound_error
69 #define Caml_array_bound_error caml_array_bound_error
71 #endif
73 #ifndef SYS_solaris
74 #define INDIRECT_LIMIT
75 #endif
77 #define Exn_ptr %l5
78 #define Alloc_ptr %l6
79 #define Alloc_limit %l7
81 #define Load(symb,reg)  sethi %hi(symb), %g1; ld [%g1 + %lo(symb)], reg
82 #define Store(reg,symb) sethi %hi(symb), %g1; st reg, [%g1 + %lo(symb)]
83 #define Address(symb,reg) sethi %hi(symb), reg; or reg, %lo(symb), reg
85 /* Allocation functions */
87         .text
88         .global Caml_allocN
89         .global Caml_call_gc
91 /* Required size in %g2 */
92 Caml_allocN:
93 #ifdef INDIRECT_LIMIT
94         ld      [Alloc_limit], %g1
95         sub     Alloc_ptr, %g2, Alloc_ptr
96         cmp     Alloc_ptr, %g1
97 #else
98         sub     Alloc_ptr, %g2, Alloc_ptr
99         cmp     Alloc_ptr, Alloc_limit
100 #endif
101         /*blu,pt  %icc, Caml_call_gc*/
102         blu     Caml_call_gc
103         nop
104         retl
105         nop
107 /* Required size in %g2 */
108 Caml_call_gc:
109     /* Save exception pointer if GC raises */
110         Store(Exn_ptr, Caml_exception_pointer)
111     /* Save current allocation pointer for debugging purposes */
112         Store(Alloc_ptr, Caml_young_ptr)
113     /* Record lowest stack address */
114         Store(%sp, Caml_bottom_of_stack)
115     /* Record last return address */
116         Store(%o7, Caml_last_return_address)
117     /* Allocate space on stack for caml_context structure and float regs */
118         sub     %sp, 20*4 + 15*8, %sp
119     /* Save int regs on stack and save it into caml_gc_regs */
120 L100:   add     %sp, 96 + 15*8, %g1
121         st      %o0, [%g1]
122         st      %o1, [%g1 + 0x4]
123         st      %o2, [%g1 + 0x8]
124         st      %o3, [%g1 + 0xc]
125         st      %o4, [%g1 + 0x10]
126         st      %o5, [%g1 + 0x14]
127         st      %i0, [%g1 + 0x18]
128         st      %i1, [%g1 + 0x1c]
129         st      %i2, [%g1 + 0x20]
130         st      %i3, [%g1 + 0x24]
131         st      %i4, [%g1 + 0x28]
132         st      %i5, [%g1 + 0x2c]
133         st      %l0, [%g1 + 0x30]
134         st      %l1, [%g1 + 0x34]
135         st      %l2, [%g1 + 0x38]
136         st      %l3, [%g1 + 0x3c]
137         st      %l4, [%g1 + 0x40]
138         st      %g3, [%g1 + 0x44]
139         st      %g4, [%g1 + 0x48]
140         st      %g2, [%g1 + 0x4C]       /* Save required size */
141         mov     %g1, %g2
142         Store(%g2, Caml_gc_regs)
143     /* Save the floating-point registers */
144         add     %sp, 96, %g1
145         std     %f0, [%g1]
146         std     %f2, [%g1 + 0x8]
147         std     %f4, [%g1 + 0x10]
148         std     %f6, [%g1 + 0x18]
149         std     %f8, [%g1 + 0x20]
150         std     %f10, [%g1 + 0x28]
151         std     %f12, [%g1 + 0x30]
152         std     %f14, [%g1 + 0x38]
153         std     %f16, [%g1 + 0x40]
154         std     %f18, [%g1 + 0x48]
155         std     %f20, [%g1 + 0x50]
156         std     %f22, [%g1 + 0x58]
157         std     %f24, [%g1 + 0x60]
158         std     %f26, [%g1 + 0x68]
159         std     %f28, [%g1 + 0x70]
160     /* Call the garbage collector */
161         call    Caml_garbage_collection
162         nop
163     /* Restore all regs used by the code generator */
164         add     %sp, 96 + 15*8, %g1
165         ld      [%g1], %o0
166         ld      [%g1 + 0x4], %o1
167         ld      [%g1 + 0x8], %o2
168         ld      [%g1 + 0xc], %o3
169         ld      [%g1 + 0x10], %o4
170         ld      [%g1 + 0x14], %o5
171         ld      [%g1 + 0x18], %i0
172         ld      [%g1 + 0x1c], %i1
173         ld      [%g1 + 0x20], %i2
174         ld      [%g1 + 0x24], %i3
175         ld      [%g1 + 0x28], %i4
176         ld      [%g1 + 0x2c], %i5
177         ld      [%g1 + 0x30], %l0
178         ld      [%g1 + 0x34], %l1
179         ld      [%g1 + 0x38], %l2
180         ld      [%g1 + 0x3c], %l3
181         ld      [%g1 + 0x40], %l4
182         ld      [%g1 + 0x44], %g3
183         ld      [%g1 + 0x48], %g4
184         ld      [%g1 + 0x4C], %g2     /* Recover desired size */
185         add     %sp, 96, %g1
186         ldd     [%g1], %f0
187         ldd     [%g1 + 0x8], %f2
188         ldd     [%g1 + 0x10], %f4
189         ldd     [%g1 + 0x18], %f6
190         ldd     [%g1 + 0x20], %f8
191         ldd     [%g1 + 0x28], %f10
192         ldd     [%g1 + 0x30], %f12
193         ldd     [%g1 + 0x38], %f14
194         ldd     [%g1 + 0x40], %f16
195         ldd     [%g1 + 0x48], %f18
196         ldd     [%g1 + 0x50], %f20
197         ldd     [%g1 + 0x58], %f22
198         ldd     [%g1 + 0x60], %f24
199         ldd     [%g1 + 0x68], %f26
200         ldd     [%g1 + 0x70], %f28
201     /* Reload alloc ptr */
202         Load(Caml_young_ptr, Alloc_ptr)
203     /* Allocate space for block */
204 #ifdef INDIRECT_LIMIT
205         ld      [Alloc_limit], %g1
206         sub     Alloc_ptr, %g2, Alloc_ptr
207         cmp     Alloc_ptr, %g1      /* Check that we have enough free space */
208 #else
209         Load(Caml_young_limit,Alloc_limit)
210         sub     Alloc_ptr, %g2, Alloc_ptr
211         cmp     Alloc_ptr, Alloc_limit
212 #endif
213         blu     L100                /* If not, call GC again */
214         nop
215     /* Return to caller */
216         Load(Caml_last_return_address, %o7)
217         retl
218         add     %sp, 20*4 + 15*8, %sp       /* in delay slot */
220 /* Call a C function from Caml */
222         .global Caml_c_call
223 /* Function to call is in %g2 */
224 Caml_c_call:
225     /* Record lowest stack address and return address */
226         Store(%sp, Caml_bottom_of_stack)
227         Store(%o7, Caml_last_return_address)
228     /* Save the exception handler and alloc pointer */
229         Store(Exn_ptr, Caml_exception_pointer)
230         sethi   %hi(Caml_young_ptr), %g1
231     /* Call the C function */
232         call    %g2
233         st      Alloc_ptr, [%g1 + %lo(Caml_young_ptr)]   /* in delay slot */
234     /* Reload return address */
235         Load(Caml_last_return_address, %o7)
236     /* Reload alloc pointer */
237         sethi   %hi(Caml_young_ptr), %g1
238     /* Return to caller */
239         retl
240         ld      [%g1 + %lo(Caml_young_ptr)], Alloc_ptr   /* in delay slot */
242 /* Start the Caml program */
244         .global Caml_start_program
245 Caml_start_program:
246     /* Save all callee-save registers */
247         save    %sp, -96, %sp
248     /* Address of code to call */
249         Address(Caml_program, %l2)
251     /* Code shared with caml_callback* */
252 L108:
253     /* Set up a callback link on the stack. */
254         sub     %sp, 16, %sp
255         Load(Caml_bottom_of_stack, %l0)
256         Load(Caml_last_return_address, %l1)
257         Load(Caml_gc_regs, %l3)
258         st      %l0, [%sp + 96]
259         st      %l1, [%sp + 100]
260     /* Set up a trap frame to catch exceptions escaping the Caml code */
261         call    L111
262         st      %l3, [%sp + 104]
263         b       L110
264         nop
265 L111:   sub     %sp, 8, %sp
266         Load(Caml_exception_pointer, Exn_ptr)
267         st      %o7, [%sp + 96]
268         st      Exn_ptr, [%sp + 100]
269         mov     %sp, Exn_ptr
270     /* Reload allocation pointers */
271         Load(Caml_young_ptr, Alloc_ptr)
272 #ifdef INDIRECT_LIMIT
273         Address(Caml_young_limit, Alloc_limit)
274 #else
275         Load(Caml_young_limit, Alloc_limit)
276 #endif
277     /* Call the Caml code */
278 L109:   call    %l2
279         nop
280     /* Pop trap frame and restore caml_exception_pointer */
281         ld      [%sp + 100], Exn_ptr
282         add     %sp, 8, %sp
283         Store(Exn_ptr, Caml_exception_pointer)
284     /* Pop callback link, restoring the global variables */
285 L112:   ld      [%sp + 96], %l0
286         ld      [%sp + 100], %l1
287         ld      [%sp + 104], %l2
288         Store(%l0, Caml_bottom_of_stack)
289         Store(%l1, Caml_last_return_address)
290         Store(%l2, Caml_gc_regs)
291         add     %sp, 16, %sp
292     /* Save allocation pointer */
293         Store(Alloc_ptr, Caml_young_ptr)
294     /* Reload callee-save registers and return */
295         ret
296         restore %o0, 0, %o0     /* copy %o0 in this window to caller's %o0 */
297 L110:
298     /* The trap handler */
299         Store(Exn_ptr, Caml_exception_pointer)
300     /* Encode exception bucket as an exception result */
301         b       L112
302         or      %o0, 2, %o0
304 /* Raise an exception from C */
306         .global Caml_raise_exception
307 Caml_raise_exception:
308     /* Save exception bucket in a register outside the reg windows */
309         mov     %o0, %g2
310     /* Load exception pointer in a register outside the reg windows */
311         Load(Caml_exception_pointer, %g3)
312     /* Pop some frames until the trap pointer is in the current frame. */
313         cmp     %g3, %fp
314         blt     L107                    /* if Exn_ptr < %fp, over */
315         nop
316 L106:   restore
317         cmp     %fp, %g3                /* if %fp <= Exn_ptr, loop */
318         ble     L106
319         nop
320 L107:
321     /* Reload allocation registers */
322         Load(Caml_young_ptr, Alloc_ptr)
323 #ifdef INDIRECT_LIMIT
324         Address(Caml_young_limit, Alloc_limit)
325 #else
326         Load(Caml_young_limit, Alloc_limit)
327 #endif
328     /* Branch to exception handler */
329         mov     %g3, %sp
330         ld      [%sp + 96], %g1
331         ld      [%sp + 100], Exn_ptr
332         add     %sp, 8, %sp
333         jmp     %g1 + 8
334     /* Restore bucket, in delay slot */
335         mov     %g2, %o0
337 /* Callbacks C -> ML */
339         .global Caml_callback_exn
340 Caml_callback_exn:
341     /* Save callee-save registers and return address */
342         save    %sp, -96, %sp
343     /* Initial shuffling of arguments */
344         mov     %i0, %g1
345         mov     %i1, %i0        /* first arg */
346         mov     %g1, %i1        /* environment */
347         b       L108
348         ld      [%g1], %l2      /* code pointer */
350         .global Caml_callback2_exn
351 Caml_callback2_exn:
352     /* Save callee-save registers and return address */
353         save    %sp, -104, %sp
354     /* Initial shuffling of arguments */
355         mov     %i0, %g1
356         mov     %i1, %i0        /* first arg */
357         mov     %i2, %i1        /* second arg */
358         mov     %g1, %i2        /* environment */
359         sethi   %hi(Caml_apply2), %l2
360         b       L108
361         or      %l2, %lo(Caml_apply2), %l2
363         .global Caml_callback3_exn
364 Caml_callback3_exn:
365     /* Save callee-save registers and return address */
366         save    %sp, -104, %sp
367     /* Initial shuffling of arguments */
368         mov     %i0, %g1
369         mov     %i1, %i0        /* first arg */
370         mov     %i2, %i1        /* second arg */
371         mov     %i3, %i2        /* third arg */
372         mov     %g1, %i3        /* environment */
373         sethi   %hi(Caml_apply3), %l2
374         b       L108
375         or      %l2, %lo(Caml_apply3), %l2
377 #ifndef SYS_solaris
378 /* Glue code to call [caml_array_bound_error] */
380         .global Caml_ml_array_bound_error
381 Caml_ml_array_bound_error:
382         Address(Caml_array_bound_error, %g2)
383         b       Caml_c_call
384         nop
385 #endif
387 #ifdef SYS_solaris
388         .section ".rodata"
389 #else
390         .data
391 #endif
392         .global Caml_system__frametable
393         .align  4               /* required for gas? */
394 Caml_system__frametable:
395         .word   1               /* one descriptor */
396         .word   L109            /* return address into callback */
397         .half   -1              /* negative frame size => use callback link */
398         .half   0               /* no roots */
400 #ifdef SYS_solaris
401         .type Caml_allocN, #function
402         .type Caml_call_gc, #function
403         .type Caml_c_call, #function
404         .type Caml_start_program, #function
405         .type Caml_raise_exception, #function
406         .type Caml_system__frametable, #object
407 #endif