Merged revisions 7940-8026 via svnmerge from
[cacao.git] / src / vm / jit / sparc64 / asmpart.S
1 /* src/vm/jit/sparc64/asmpart.S - Java-C interface functions for Sparc64
2
3    Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25    $Id: asmpart.S 4749 2006-04-11 10:20:18Z twisti $
26
27 */
28
29
30 #include "config.h"
31
32 #include "vm/jit/sparc64/md-abi.h"
33 #include "offsets.h"
34 #include "md-asm.h"
35
36         .register %g2,#scratch                         /* define as scratch       */
37         .register %g3,#scratch                    /* XXX  reserve for application */
38         .text
39
40 /* export functions ***********************************************************/
41
42         .global asm_vm_call_method        
43         .global asm_vm_call_method_int    
44         .global asm_vm_call_method_long   
45         .global asm_vm_call_method_float  
46         .global asm_vm_call_method_double 
47         .global asm_vm_call_method_exception_handler
48         .global asm_vm_call_method_end
49
50         .global asm_call_jit_compiler
51
52         .global asm_handle_exception
53         .global asm_handle_nat_exception
54
55         .global asm_patcher_wrapper
56
57         .global asm_abstractmethoderror
58         
59         .global asm_criticalsections
60         .global asm_getclassvalues_atomic
61         
62         .global asm_store_fp_state_reg
63         .global asm_load_fp_state_reg
64
65
66 /* asm_vm_call_method ******************************************************
67  *                                                                         *
68  * This function calls a Java-method (which possibly needs compilation)    *
69  *
70  * If the java method is throwing an exception, NULL will be returned.
71  *
72  * C-prototype:
73  *  java_objectheader *asm_vm_call_method(methodinfo *m, s4 vmargscount,
74  *                                               vm_arg *vmargs);
75  **************************************************************************/
76
77         .align 8        /* v9: All data types are aligned to their size */
78
79         .xword 0                         /* catch type all */
80         .xword 0                         /* handler pc */
81         .xword 0                         /* end pc */
82         .xword 0                         /* start pc */
83         .word  1                         /* extable size */
84         .word  0                         /* ALIGNMENT PADDING */
85         .xword 0                         /* line number table start */
86         .xword 0                         /* line number table size */
87         .word  0                         /* ALIGNMENT PADDING */
88         .word  0                         /* fltsave */
89         .word  1                         /* intsave */
90         .word  0                         /* isleaf */
91         .word  0                         /* IsSync */
92         .word  0                         /* frame size */
93         .xword 0                         /* method pointer (pointer to name)*/ 
94
95 asm_vm_call_method:       
96 asm_vm_call_method_int:   
97 asm_vm_call_method_long:  
98 asm_vm_call_method_float: 
99 asm_vm_call_method_double:
100         
101         save %sp,-((JITSTACK_CNT+2)*8),%sp
102         add %sp,JITSTACK,%l1               /* right above window save area */
103
104
105         /* %i1 not needed after _nocopy -> calculate in branch delay */
106
107         brlez %i1, calljava_nocopy
108         
109         dec %i1   /* branch delay */
110         ldx [%i2 + offvmargdata],%o0
111         ldx [%i2 + offvmargtype],%l2
112         cmp %l2,2
113         be,a %xcc,calljava_arg0isfloat
114         ld  [%i2 + offvmargdata],fa0f   /* delay: annulled if branch not taken */
115         ldd [%i2 + offvmargdata],fa0
116 calljava_arg0isfloat:
117         brlez %i1,calljava_nocopy
118
119         dec %i1   /* branch delay */
120         ldx [%i2 + (offvmargdata+sizevmarg*1)],%o1
121         ldx [%i2 + (offvmargtype+sizevmarg*1)],%l2
122         cmp %l2,2
123         be,a %xcc,calljava_arg1isfloat
124         ld  [%i2 + (offvmargdata+sizevmarg*1)],fa1f
125         ldd [%i2 + (offvmargdata+sizevmarg*1)],fa1
126 calljava_arg1isfloat:
127         brlez %i1,calljava_nocopy
128
129         dec %i1
130         ldx [%i2 + (offvmargdata+sizevmarg*2)],%o2
131         ldx [%i2 + (offvmargtype+sizevmarg*2)],%l2
132         cmp %l2,2
133         be,a %xcc,calljava_arg2isfloat
134         ld  [%i2 + (offvmargdata+sizevmarg*2)],fa2f
135         ldd [%i2 + (offvmargdata+sizevmarg*2)],fa2
136 calljava_arg2isfloat:
137         brlez %i1,calljava_nocopy
138
139         dec %i1
140         ldx [%i2 + (offvmargdata+sizevmarg*3)],%o3
141         ldx [%i2 + (offvmargtype+sizevmarg*3)],%l2
142         cmp %l2,2
143         be,a %xcc,calljava_arg3isfloat
144         ld  [%i2 + (offvmargdata+sizevmarg*3)],fa3f
145         ldd [%i2 + (offvmargdata+sizevmarg*3)],fa3
146 calljava_arg3isfloat:
147         brlez %i1,calljava_nocopy
148
149         dec %i1
150         ldx [%i2 + (offvmargdata+sizevmarg*4)],%o4
151         ldx [%i2 + (offvmargtype+sizevmarg*4)],%l2
152         cmp %l2,2
153         be,a %xcc,calljava_arg4isfloat
154         ld  [%i2 + (offvmargdata+sizevmarg*4)],fa4f
155         ldd [%i2 + (offvmargdata+sizevmarg*4)],fa4
156 calljava_arg4isfloat:
157
158 calljava_argsloaded:    
159         brlez %i1, calljava_nocopy
160         nop
161         sllx %i1,3,%l0                     /* remaining args * 8           */
162         sub %sp,%l0,%sp                    /* allocate more stack space    */
163         add %sp,JITSTACK,%l1               /* adjust stack begin pointer   */
164         
165 calljava_copyloop:
166         ldx [%i2 + (offvmargtype+sizevmarg*5)],%l2
167         cmp %l2,2
168         be  %xcc,calljava_copyloop_float
169         nop
170         ldx [%i2 + (offvmargdata+sizevmarg*5)],%l0
171         stx %l0,[%l1]
172         b   calljava_copy_done
173 calljava_copyloop_float:
174         ld  [%i2 + (offvmargdata+sizevmarg*5)],%f1      
175         std %f0,[%l1]
176 calljava_copy_done:
177         inc sizevmarg,%i2                  /* src++                        */
178         subcc %i1,1,%i1                    /* arg_count--                  */
179         bnz %xcc, calljava_copyloop        /* use cc from previous instr   */
180         inc 8,%l1                          /* dst++ (delay)                */
181         
182
183 calljava_nocopy:
184         /* set pv, like a java method does */
185         /*      add  ra_caller,(asm_vm_call_method - calljava_nocopy + 8),pv_callee */
186         setx  asm_vm_call_method,%l0,pv_callee
187         
188         mov   %i0,itmp1         /* pass method info pointer via itmp1 */
189         
190         setx  asm_call_jit_compiler,%l0,mptr_itmp2  /* fake virtual function call (2 instr) */
191         stx   mptr_itmp2,[%l1 + 1*8]        /* store function address               */
192         mov   %l1,mptr_itmp2            /* set method pointer                   */
193         
194         ldx  [1*8 + mptr_itmp2], pv_caller          /* method call as in Java               */
195         jmpl pv_caller,ra_caller                      /* call JIT compiler          */
196         nop
197 calljava_jit2:
198         /* pretend to restore pv */
199         add  ra_caller,(asm_vm_call_method - calljava_jit2 + 8),zero
200         
201 calljava_return:
202         mov %o0, %i0            /* pass on the return value     */
203         return %i7 + 8          /* implicit window restore */
204         nop
205
206
207 asm_vm_call_method_exception_handler:
208         
209         /* so far this function did not call any c functions */
210         /* but now we need ABI compliant argslots on the stack */
211         sub   %sp,6*8,%sp
212         
213         mov             xptr_itmp2,%o0
214         call    builtin_throw_exception
215         nop
216         return  %i7 + 8                          /* implicit window restore */
217 asm_vm_call_method_end:
218         mov    zero,%o0                  /* delay: return NULL      */
219         
220
221
222 /****************** function asm_call_jit_compiler *****************************
223 *                                                                              *
224 *   invokes the compiler for untranslated JavaVM methods.                      *
225 *                                                                              *
226 *   Register R0 contains a pointer to the method info structure (prepared      *
227 *   by createcompilerstub). Using the return address in R26 and the            *
228 *   offset in the LDA instruction or using the value in methodptr R28 the      *
229 *   patching address for storing the method address can be computed:           *
230 *                                                                              *
231 *   method address was either loaded using                                     *
232 *   M_LDQ (REG_PV, REG_PV, a)        ; invokestatic/special    ($27)           *
233 *   M_LDA (REG_PV, REG_RA, low)                                                *
234 *   M_LDAH(REG_PV, REG_RA, high)     ; optional                                *
235 *   or                                                                         *
236 *   M_LDQ (REG_PV, REG_METHODPTR, m) ; invokevirtual/interface ($28)           *
237 *   in the static case the method pointer can be computed using the            *
238 *   return address and the lda function following the jmp instruction          *
239 *                                                                              *
240 *******************************************************************************/
241
242 asm_call_jit_compiler:
243         
244         /* stacksave for regsave(16) + argslots(6) + float args  */
245         /* Note: +1 to keep stack 16-byte aligned                */
246         save    %sp,-((16+6+FLT_ARG_CNT+1)*8),%sp
247
248         SAVE_FLOAT_ARGUMENT_REGISTERS(22)
249
250         mov     itmp1,%o0             /* pass methodinfo pointer                  */
251         mov     mptr_itmp2,%o1        /* pass method pointer                      */
252         mov     %fp,%o2                           /* pass java sp (==fp)                          */
253         mov     ra_callee,%o3         /* pass Java ra                             */
254         mov     %o3,%o4               /* xpc is equal to ra                       */
255         call    jit_asm_compile       /* call jit compiler                        */
256         nop
257         
258         RESTORE_FLOAT_ARGUMENT_REGISTERS(22)
259
260         brz     %o0,L_asm_call_jit_compiler_exception
261         nop
262         
263         restore %o0,%g0,pv_caller     /* restore the callers window               */
264                                       /* the source o0 references the old window  */
265                                       /* pv_caller references the new window      */
266
267
268         /* synchronise instruction cache moved somewhere else           */
269
270         jmpl    pv_caller,zero        /* and call method, the method returns      */
271                                       /* directly to the caller (ra).             */
272         nop     
273         
274 L_asm_call_jit_compiler_exception:
275         /* window still open, ra_callee valid, pv_callee undefined      */
276
277         call    exceptions_get_and_clear_exception
278         nop
279
280         mov     %o0,xptr_itmp2        /* get exception                            */
281         mov     ra_callee,xpc_itmp3  /* exception address is address of call      */
282
283         /* restore the window of the calling function */
284         restore
285
286         b      L_asm_handle_nat_exception
287         nop
288
289
290
291 /* asm_handle_exception ********************************************************
292
293    This function handles an exception. It does not use the usual calling
294    conventions. The exception pointer is passed in REG_ITMP2 and the
295    pc from the exception raising position is passed in REG_ITMP3. It searches
296    the local exception table for a handler. If no one is found, it unwinds
297    stacks and continues searching the callers.
298
299 *******************************************************************************/
300
301
302 asm_handle_nat_exception:
303 L_asm_handle_nat_exception:       /* required for PIC code                    */
304 L_asm_handle_exception_stack_loop:
305         /* exception handling assumes that the current java method saved       */
306         /* the caller's window, and has a valid pv                             */
307
308         /* get ra and pv before saving the window */
309         mov     ra_callee,itmp1
310         mov     pv_callee,%g4
311
312         save    %sp,-176,%sp
313         mov     xptr_itmp2,%l0              /* save exception pointer             */
314         mov     xpc_itmp3,%l1               /* save exception pc                  */
315         mov     zero,%l2                    /* save maybe-leaf flag (cleared)     */
316
317         mov     %l0,%o0                     /* pass xptr                          */
318         mov     %l1,%o1                     /* pass xpc                           */
319         mov     %g4,%o2                     /* pass PV                            */
320         mov     %fp,%o3                     /* pass Java SP                       */
321
322         b       L_asm_handle_exception_continue
323         nop
324
325 asm_handle_exception:
326         mov     pv_callee,%g4
327
328         /* save bigger stack frame for float args and temps */
329         save    %sp,-((FLT_ARG_CNT+FLT_TMP_CNT+CSTACK_CNT)*8),%sp
330
331         SAVE_FLOAT_ARGUMENT_REGISTERS(CSTACK_CNT)
332         SAVE_FLOAT_TEMPORARY_REGISTERS(CSTACK_CNT+FLT_ARG_CNT)
333
334         mov     xptr_itmp2,%l0              /* save exception pointer             */
335         add     zero,1,%l2                  /* set maybe-leaf flag                */
336
337         mov     %l0,%o0                     /* pass xptr                          */
338         mov     xpc_itmp3,%o1               /* pass xpc                           */
339         mov     %g4,%o2                     /* pass PV                            */
340         mov     %fp,%o3                     /* pass Java SP                       */
341
342 L_asm_handle_exception_continue:
343         call    exceptions_handle_exception
344         nop
345
346         brz     %o0,L_asm_handle_exception_not_caught
347         nop
348
349         mov     %o0,xpc_itmp3               /* move handlerpc into xpc            */
350         mov     %l0,xptr_itmp2              /* restore exception pointer          */
351
352         brz     %l2,L_asm_handle_exception_no_leaf
353         nop
354
355         RESTORE_FLOAT_ARGUMENT_REGISTERS(CSTACK_CNT)
356         RESTORE_FLOAT_TEMPORARY_REGISTERS(CSTACK_CNT+FLT_ARG_CNT)
357         
358 L_asm_handle_exception_no_leaf:
359         /* restore java window and stackframe (ra and pv are in there) */
360         restore
361         jmpl    xpc_itmp3, zero             /* jump to the handler                */
362         nop
363
364 L_asm_handle_exception_not_caught:
365         mov     %l0,xptr_itmp2              /* restore xptr                       */
366         restore                             /* free our stackframe and window     */
367         /* maybe leaf flag gets cleared after branch to _loop */
368         
369         restore                             /* unwind stack and window            */
370         ba      L_asm_handle_exception_stack_loop
371         mov     ra_caller,xpc_itmp3         /* the new xpc is ra (delay)          */
372         
373
374
375
376 /* asm_abstractmethoderror *****************************************************
377
378    Creates and throws an AbstractMethodError.
379
380 *******************************************************************************/
381
382 asm_abstractmethoderror:
383         /* do a window save */
384         save %sp,-192,%sp
385
386         mov     %fp,%o0                     /* pass java sp(==fp)                 */
387         mov     ra_callee,%o1               /* pass exception address             */
388         call    exceptions_asm_new_abstractmethoderror
389         nop
390
391         mov     %o0,xptr_itmp2              /* get exception pointer              */
392         sub     ra_callee,4,xpc_itmp3       /* exception address is ra - 4        */
393         ba      L_asm_handle_nat_exception
394         nop
395
396         /* XXX: leave the register window open for handle_exception ??? */
397
398 /* asm_patcher_wrapper *********************************************************
399
400    XXX
401
402    Stack layout, when called from patcher stub
403      40   return address into JIT code (patch position)
404      32   pointer to virtual java_objectheader
405      24   machine code (which is patched back later)
406      16   unresolved class/method/field reference
407       8   data segment displacement from load instructions
408       0   patcher function pointer to call
409    -128   WINSAVE REGS (current SP)
410
411 *******************************************************************************/
412                 
413
414 asm_patcher_wrapper:
415         /* get pv and ra, since the emit code is not passing it on */
416         mov     ra_callee,ra_caller
417         mov     pv_callee,pv_caller
418
419         /* create window and stack frame              */
420         save  %sp,-((FLT_ARG_CNT+FLT_TMP_CNT+CSTACK_CNT+6)*8),%sp
421
422         SAVE_FLOAT_RETURN_REGISTER(CSTACK_CNT)
423         SAVE_FLOAT_ARGUMENT_REGISTERS(CSTACK_CNT+1)
424         SAVE_FLOAT_TEMPORARY_REGISTERS(CSTACK_CNT+1+FLT_ARG_CNT)
425
426         mov     itmp1,%l0               /* save itmp1                             */
427         mov     itmp2,%l1               /* save itmp2                             */
428
429         add     %fp,JITSTACK,%o0      /* pass pseudo SP                           */
430         mov     pv_callee,%o1         /* pass PV                                  */
431         mov     ra_callee,%o2         /* pass RA (correct for leafs)              */
432         call    patcher_wrapper
433         nop
434
435         RESTORE_FLOAT_RETURN_REGISTER(CSTACK_CNT)
436         RESTORE_FLOAT_ARGUMENT_REGISTERS(CSTACK_CNT+1)
437         RESTORE_FLOAT_TEMPORARY_REGISTERS(CSTACK_CNT+1+FLT_ARG_CNT)
438
439         mov     %l0,itmp1               /* restore itmp1                          */
440         mov     %l1,itmp2               /* restore itmp2                          */
441
442         brnz    %o0,L_asm_patcher_wrapper_exception
443         nop
444
445         /* load RA (patch position from patcher data on the stack */
446         ldx     [%fp+JITSTACK+5*8],itmp3
447
448         /* remove window and stack frame (and stack space allocated in the stub code */
449         restore  %fp,6*8,%sp /* (source regs refer to old window, rd to new window)  */
450
451         jmpl     itmp3,zero              /* jump to newly patched code               */
452         nop
453
454 L_asm_patcher_wrapper_exception:
455         mov      %o0,xptr_itmp2        /* get exception                            */
456         ldx      [%fp+JITSTACK+5*8],xpc_itmp3 /* xpc is RA                         */
457         restore  %fp,6*8,%sp           /* remove stack frame                       */
458         ba       asm_handle_exception
459         nop
460
461
462     
463 /* asm_store_fp_state_reg **************************************************
464  *                                                                         *
465  * This function stores the 64-bit floating point state register to a      *
466  * memory location. (which needs to be 8-byte aligned)                     *
467  *                                                                         *
468  * C-prototype:                                                            *
469  *  void asm_store_fp_state_reg(u8 *mem);                                  *
470  *                                                                             *
471  **************************************************************************/
472  
473 asm_store_fp_state_reg:
474         stx %fsr,[%o0]
475         retl  /* return from leaf */
476         nop
477         
478 /* asm_load_fp_state_reg ***************************************************
479  *                                                                         *
480  * This function loades the 64-bit floating point state register from a    *
481  * memory location. (which needs to be 8-byte aligned)                     *
482  *                                                                         *
483  * C-prototype:                                                            *
484  *  void asm_load_fp_state_reg(u8 *mem);                                   *
485  *                                                                             *
486  **************************************************************************/
487  
488 asm_load_fp_state_reg:
489         ldx [%o0],%fsr
490         retl  /* return from leaf */
491         nop
492
493
494
495
496 asm_getclassvalues_atomic:
497 _crit_restart:
498 _crit_begin:
499 /* not doing a window save, using the global temporary registers */
500         ldsw    [offbaseval+%o0],itmp1
501         ldsw    [offdiffval+%o0],itmp2
502         ldsw    [offbaseval+%o1],itmp3
503 _crit_end:
504         stw     itmp1,[offcast_super_baseval+%o2]
505         stw     itmp2,[offcast_super_diffval+%o2]
506         stw     itmp3,[offcast_sub_baseval+%o2]
507         jmpl    ra_caller+8,zero  /* caller's ra, b/c no window save */
508         nop
509
510
511     .data
512
513 asm_criticalsections:
514 #if defined(ENABLE_THREADS)
515     .xword   _crit_begin
516     .xword   _crit_end
517     .xword   _crit_restart
518 #endif
519     .xword   0
520     
521
522 /* disable exec-stacks ********************************************************/
523
524 #if defined(__linux__) && defined(__ELF__)
525         .section .note.GNU-stack,"",%progbits
526 #endif
527
528
529 /*
530  * These are local overrides for various environment variables in Emacs.
531  * Please do not remove this and leave it at the end of the file, where
532  * Emacs will automagically detect them.
533  * ---------------------------------------------------------------------
534  * Local variables:
535  * mode: asm
536  * indent-tabs-mode: t
537  * c-basic-offset: 4
538  * tab-width: 4
539  * End:
540  * vim:noexpandtab:sw=4:ts=4:
541  */