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