/* src/vm/jit/sparc64/asmpart.S - Java-C interface functions for Sparc64 Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger, Institut f. Computersprachen - TU Wien This file is part of CACAO. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. $Id: asmpart.S 4749 2006-04-11 10:20:18Z twisti $ */ #include "config.h" #include "vm/jit/sparc64/md-abi.h" #include "offsets.h" #include "md-asm.h" .register %g2,#scratch /* define as scratch */ .register %g3,#scratch /* XXX reserve for application */ .text /* export functions ***********************************************************/ .global asm_vm_call_method .global asm_vm_call_method_int .global asm_vm_call_method_long .global asm_vm_call_method_float .global asm_vm_call_method_double .global asm_vm_call_method_exception_handler .global asm_vm_call_method_end .global asm_call_jit_compiler .global asm_handle_exception .global asm_handle_nat_exception .global asm_patcher_wrapper .global asm_abstractmethoderror .global asm_criticalsections .global asm_getclassvalues_atomic .global asm_store_fp_state_reg .global asm_load_fp_state_reg /* asm_vm_call_method ****************************************************** * * * This function calls a Java-method (which possibly needs compilation) * * * C-prototype: * java_objectheader *asm_vm_call_method(methodinfo *m, s4 vmargscount, * vm_arg *vmargs); **************************************************************************/ .align 8 /* v9: All data types are aligned to their size */ .xword 0 /* catch type all */ .xword 0 /* handler pc */ .xword 0 /* end pc */ .xword 0 /* start pc */ .word 1 /* extable size */ .word 0 /* ALIGNMENT PADDING */ .xword 0 /* line number table start */ .xword 0 /* line number table size */ .word 0 /* ALIGNMENT PADDING */ .word 0 /* fltsave */ .word 1 /* intsave */ .word 0 /* isleaf */ .word 0 /* IsSync */ .word 0 /* frame size */ .xword 0 /* method pointer (pointer to name)*/ asm_vm_call_method: asm_vm_call_method_int: asm_vm_call_method_long: asm_vm_call_method_float: asm_vm_call_method_double: save %sp,-144,%sp /* 16 reg-save + 2 */ /* %i2 not needed after _nocopy -> calculate in branch delay */ brlez %i1, calljava_nocopy dec %i1 /* branch delay */ ldx [%i2 + offvmargdata],%o0 ldd [%i2 + offvmargdata],fa0 brlez %i1,calljava_nocopy dec %i1 /* branch delay */ ldx [%i2 + (offvmargdata+sizevmarg*1)],%o1 ldd [%i2 + (offvmargdata+sizevmarg*1)],fa1 brlez %i1,calljava_nocopy dec %i1 ldx [%i2 + (offvmargdata+sizevmarg*2)],%o2 ldd [%i2 + (offvmargdata+sizevmarg*2)],fa2 brlez %i1,calljava_nocopy dec %i1 ldx [%i2 + (offvmargdata+sizevmarg*3)],%o3 ldd [%i2 + (offvmargdata+sizevmarg*3)],fa3 brlez %i1,calljava_nocopy dec %i1 ldx [%i2 + (offvmargdata+sizevmarg*4)],%o4 ldd [%i2 + (offvmargdata+sizevmarg*4)],fa4 calljava_argsloaded: brlez %i1, calljava_nocopy nop sllx %i1,3,%l0 /* remaining args * 8 */ add %sp,16*8+bias,%l1 /* right above window save area */ sub %sp,%l0,%sp /* allocate more stack space */ calljava_copyloop: ldx [%i2 + (offvmargdata+sizevmarg*5)],%l0 stx %l0,[%l1] inc sizevmarg,%i2 /* src++ */ subcc %i1,1,%i1 /* arg_count-- */ bnz %xcc, calljava_copyloop /* use cc from previous instr */ inc 8,%l1 /* dst++ (delay) */ calljava_nocopy: /* set pv, like a java method does */ /* add ra_caller,(asm_vm_call_method - calljava_nocopy + 8),pv_callee */ setx asm_vm_call_method,%l0,pv_callee mov %i0,itmp1 /* pass method info pointer via itmp1 */ setx asm_call_jit_compiler,%l0,mptr_itmp2 /* fake virtual function call (2 instr) */ stx mptr_itmp2,[%sp + 2047 + 17*8] /* store function address */ add %sp,2047 + 16*8,mptr_itmp2 /* set method pointer */ ldx [1*8 + mptr_itmp2], pv_caller /* method call as in Java */ jmpl pv_caller,ra_caller /* call JIT compiler */ nop calljava_jit2: /* pretend to restore pv */ add ra_caller,(asm_vm_call_method - calljava_jit2 + 8),zero calljava_return: mov %o0, %i0 /* pass on the return value */ return %i7 + 8 /* implicit window restore */ nop asm_vm_call_method_exception_handler: /* so far this function did not call any c functions */ /* but now we need ABI compliant argslots on the stack */ sub %sp,6*8,%sp mov xptr_itmp2,%o0 call builtin_throw_exception nop return %i7 + 8 /* implicit window restore */ asm_vm_call_method_end: nop /****************** function asm_call_jit_compiler ***************************** * * * invokes the compiler for untranslated JavaVM methods. * * * * Register R0 contains a pointer to the method info structure (prepared * * by createcompilerstub). Using the return address in R26 and the * * offset in the LDA instruction or using the value in methodptr R28 the * * patching address for storing the method address can be computed: * * * * method address was either loaded using * * M_LDQ (REG_PV, REG_PV, a) ; invokestatic/special ($27) * * M_LDA (REG_PV, REG_RA, low) * * M_LDAH(REG_PV, REG_RA, high) ; optional * * or * * M_LDQ (REG_PV, REG_METHODPTR, m) ; invokevirtual/interface ($28) * * in the static case the method pointer can be computed using the * * return address and the lda function following the jmp instruction * * * *******************************************************************************/ asm_call_jit_compiler: /* stacksave for regsave(16) + argslots(6) + float args */ save %sp,-((16+6+FLT_ARG_CNT)*8),%sp SAVE_FLOAT_ARGUMENT_REGISTERS(22) mov itmp1,%o0 /* pass methodinfo pointer */ mov mptr_itmp2,%o1 /* pass method pointer */ mov %fp,%o2 /* pass java sp (==fp) */ mov ra_callee,%o3 /* pass Java ra */ mov %o3,%o4 /* xpc is equal to ra */ call jit_asm_compile /* call jit compiler */ nop RESTORE_FLOAT_ARGUMENT_REGISTERS(22) brz %o0,L_asm_call_jit_compiler_exception nop restore %o0,%g0,pv_caller /* restore the callers window */ /* the source o0 references the old window */ /* pv_caller references the new window */ /* synchronise instruction cache moved somewhere else */ jmpl pv_caller,zero /* and call method, the method returns */ /* directly to the caller (ra). */ nop L_asm_call_jit_compiler_exception: /* window still open, ra_callee valid, pv_callee undefined */ call exceptions_get_and_clear_exception nop mov %o0,xptr_itmp2 /* get exception */ mov ra_callee,xpc_itmp3 /* exception address is address of call */ /* restore the window of the calling function */ restore b L_asm_handle_nat_exception nop /* asm_handle_exception ******************************************************** This function handles an exception. It does not use the usual calling conventions. The exception pointer is passed in REG_ITMP2 and the pc from the exception raising position is passed in REG_ITMP3. It searches the local exception table for a handler. If no one is found, it unwinds stacks and continues searching the callers. *******************************************************************************/ asm_handle_nat_exception: L_asm_handle_nat_exception: /* required for PIC code */ L_asm_handle_exception_stack_loop: /* exception handling assumes that the current java method saved */ /* the caller's window, and has a valid pv */ /* get ra and pv before saving the window */ mov ra_callee,itmp1 mov pv_callee,%g4 save %sp,-176,%sp mov xptr_itmp2,%l0 /* save exception pointer */ mov xpc_itmp3,%l1 /* save exception pc */ mov zero,%l2 /* save maybe-leaf flag (cleared) */ mov %l0,%o0 /* pass xptr */ mov %l1,%o1 /* pass xpc */ mov %g4,%o2 /* pass PV */ mov %fp,%o3 /* pass Java SP */ b L_asm_handle_exception_continue nop asm_handle_exception: mov pv_callee,%g4 /* save bigger stack frame for float args and temps */ save %sp,-((FLT_ARG_CNT+FLT_TMP_CNT+CSTACK_CNT)*8),%sp SAVE_FLOAT_ARGUMENT_REGISTERS(CSTACK_CNT) SAVE_FLOAT_TEMPORARY_REGISTERS(CSTACK_CNT+FLT_ARG_CNT) mov xptr_itmp2,%l0 /* save exception pointer */ add zero,1,%l2 /* set maybe-leaf flag */ mov %l0,%o0 /* pass xptr */ mov xpc_itmp3,%o1 /* pass xpc */ mov %g4,%o2 /* pass PV */ mov %fp,%o3 /* pass Java SP */ L_asm_handle_exception_continue: call exceptions_handle_exception nop brz %o0,L_asm_handle_exception_not_caught nop mov %o0,xpc_itmp3 /* move handlerpc into xpc */ mov %l0,xptr_itmp2 /* restore exception pointer */ brz %l2,L_asm_handle_exception_no_leaf nop RESTORE_FLOAT_ARGUMENT_REGISTERS(CSTACK_CNT) RESTORE_FLOAT_TEMPORARY_REGISTERS(CSTACK_CNT+FLT_ARG_CNT) L_asm_handle_exception_no_leaf: /* restore java window and stackframe (ra and pv are in there) */ restore jmpl xpc_itmp3, zero /* jump to the handler */ nop L_asm_handle_exception_not_caught: mov %l0,xptr_itmp2 /* restore xptr */ restore /* free our stackframe and window */ /* maybe leaf flag gets cleared after branch to _loop */ restore /* unwind stack and window */ ba L_asm_handle_exception_stack_loop mov ra_caller,xpc_itmp3 /* the new xpc is ra (delay) */ /* asm_abstractmethoderror ***************************************************** Creates and throws an AbstractMethodError. *******************************************************************************/ asm_abstractmethoderror: /* do a window save */ save %sp,-192,%sp mov %fp,%o0 /* pass java sp(==fp) */ mov ra_callee,%o1 /* pass exception address */ call exceptions_asm_new_abstractmethoderror nop mov %o0,xptr_itmp2 /* get exception pointer */ sub ra_callee,4,xpc_itmp3 /* exception address is ra - 4 */ ba L_asm_handle_nat_exception nop /* XXX: leave the register window open for handle_exception ??? */ /* asm_patcher_wrapper ********************************************************* XXX Stack layout, when called from patcher stub 40 return address into JIT code (patch position) 32 pointer to virtual java_objectheader 24 machine code (which is patched back later) 16 unresolved class/method/field reference 8 data segment displacement from load instructions 0 patcher function pointer to call -128 WINSAVE REGS (current SP) *******************************************************************************/ asm_patcher_wrapper: /* get pv and ra, since the emit code is not passing it on */ mov ra_callee,ra_caller mov pv_callee,pv_caller /* create window and stack frame */ save %sp,-((FLT_ARG_CNT+FLT_TMP_CNT+CSTACK_CNT+4)*8),%sp SAVE_FLOAT_ARGUMENT_REGISTERS(CSTACK_CNT) SAVE_FLOAT_TEMPORARY_REGISTERS(CSTACK_CNT+FLT_ARG_CNT) mov itmp1,%l0 /* save itmp1 */ mov itmp2,%l1 /* save itmp2 */ add %fp,JITSTACK,%o0 /* pass pseudo SP */ mov pv_callee,%o1 /* pass PV */ mov ra_callee,%o2 /* pass RA (correct for leafs) */ call patcher_wrapper nop RESTORE_FLOAT_ARGUMENT_REGISTERS(CSTACK_CNT) RESTORE_FLOAT_TEMPORARY_REGISTERS(CSTACK_CNT+FLT_ARG_CNT) mov %l0,itmp1 /* restore itmp1 */ mov %l1,itmp2 /* restore itmp2 */ brnz %o0,L_asm_patcher_wrapper_exception nop /* load RA (patch position from patcher data on the stack */ ldx [%fp+JITSTACK+5*8],itmp3 /* remove window and stack frame (and stack space allocated in the stub code */ restore %fp,6*8,%sp /* (source regs refer to old window, rd to new window) */ jmpl itmp3,zero /* jump to newly patched code */ nop L_asm_patcher_wrapper_exception: mov %o0,xptr_itmp2 /* get exception */ ldx [%fp+JITSTACK+5*8],xpc_itmp3 /* xpc is RA */ restore %fp,6*8,%sp /* remove stack frame */ ba asm_handle_exception nop asm_getclassvalues_atomic: _crit_restart: _crit_begin: /* not doing a window save, using the global temporary registers */ ldsw [offbaseval+%o0],itmp1 ldsw [offdiffval+%o0],itmp2 ldsw [offbaseval+%o1],itmp3 _crit_end: stw itmp1,[offcast_super_baseval+%o2] stw itmp2,[offcast_super_diffval+%o2] stw itmp3,[offcast_sub_baseval+%o2] jmpl ra_caller+8,zero /* caller's ra, b/c no window save */ nop .data asm_criticalsections: #if defined(ENABLE_THREADS) .xword _crit_begin .xword _crit_end .xword _crit_restart #endif .xword 0 /* asm_store_fp_state_reg ************************************************** * * * This function stores the 64-bit floating point state register to a * * memory location. (which needs to be 8-byte aligned) * * * * C-prototype: * * void asm_store_fp_state_reg(u8 *mem); * * * **************************************************************************/ asm_store_fp_state_reg: stx %fsr,[%o0] retl /* return from leaf */ nop /* asm_load_fp_state_reg *************************************************** * * * This function loades the 64-bit floating point state register from a * * memory location. (which needs to be 8-byte aligned) * * * * C-prototype: * * void asm_load_fp_state_reg(u8 *mem); * * * **************************************************************************/ asm_load_fp_state_reg: ldx [%o0],%fsr retl /* return from leaf */ nop /* disable exec-stacks ********************************************************/ #if defined(__linux__) && defined(__ELF__) .section .note.GNU-stack,"",%progbits #endif /* * These are local overrides for various environment variables in Emacs. * Please do not remove this and leave it at the end of the file, where * Emacs will automagically detect them. * --------------------------------------------------------------------- * Local variables: * mode: asm * indent-tabs-mode: t * c-basic-offset: 4 * tab-width: 4 * End: * vim:noexpandtab:sw=4:ts=4: */