/* src/vm/jit/alpha/asmpart.S - Java-C interface functions for alpha 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. */ #include "config.h" #include "vm/jit/alpha/md-abi.h" #include "vm/jit/alpha/md-asm.h" #include "vm/jit/abi-asm.h" #include "vm/jit/methodheader.h" .text .set noat .set noreorder /* export functions ***********************************************************/ .globl asm_vm_call_method .globl asm_vm_call_method_int .globl asm_vm_call_method_long .globl asm_vm_call_method_float .globl asm_vm_call_method_double .globl asm_vm_call_method_exception_handler .globl asm_vm_call_method_end .globl asm_call_jit_compiler .globl asm_handle_exception .globl asm_handle_nat_exception .globl asm_abstractmethoderror .globl asm_compare_and_swap .globl asm_memory_barrier .globl asm_md_init .globl asm_cacheflush /* asm_vm_call_method ********************************************************** * * * This function calls a Java-method (which possibly needs compilation) * * with up to 4 address parameters. * * * * This functions calls the JIT-compiler which eventually translates the * * method into machine code. * * * * C-prototype: * * javaobject_header *asm_calljavafunction (methodinfo *m, * * void *arg1, void *arg2, void *arg3, void *arg4); * * * *******************************************************************************/ .ent asm_vm_call_method .align 3 .quad 0 /* catch type all */ .quad 0 /* handler pc */ .quad 0 /* end pc */ .quad 0 /* start pc */ .long 1 /* extable size */ .long 0 /* ALIGNMENT PADDING */ .quad 0 /* line number table start */ .quad 0 /* line number table size */ .long 0 /* ALIGNMENT PADDING */ .long 0 /* fltsave */ .long 1 /* intsave */ .long 0 /* isleaf */ .long 0 /* IsSync */ .long 0 /* frame size */ .quad 0 /* codeinfo pointer */ asm_vm_call_method: asm_vm_call_method_int: asm_vm_call_method_long: asm_vm_call_method_float: asm_vm_call_method_double: ldgp gp,0(pv) lda sp,-5*8(sp) /* allocate stack space */ stq ra,0*8(sp) /* save return address */ stq gp,1*8(sp) /* save global pointer */ stq s0,3*8(sp) stq a0,4*8(sp) /* save method PV */ mov a1,t0 /* address of argument array */ mov a2,t1 /* stack argument count */ mov sp,s0 /* save stack pointer */ ldq a0,0*8(t0) ldq a1,1*8(t0) ldq a2,2*8(t0) ldq a3,3*8(t0) ldq a4,4*8(t0) ldq a5,5*8(t0) ldt fa0,6*8(t0) ldt fa1,7*8(t0) ldt fa2,8*8(t0) ldt fa3,9*8(t0) ldt fa4,10*8(t0) ldt fa5,11*8(t0) beq t1,L_asm_vm_call_method_stack_copy_done negq t1,t2 /* calculate stackframe size (* 8) */ s8addq t2,sp,sp /* create stackframe */ mov sp,t2 /* temporary stack pointer */ L_asm_vm_call_method_stack_copy_loop: ldq t3,12*8(t0) /* load argument */ stq t3,0(t2) /* store argument on stack */ subq t1,1,t1 /* subtract 1 argument */ addq t0,8,t0 /* load address of next argument */ addq t2,8,t2 /* increase stack pointer */ bgt t1,L_asm_vm_call_method_stack_copy_loop L_asm_vm_call_method_stack_copy_done: lda mptr,4*8(s0) /* get address of PV */ ldq pv,0*8(mptr) /* load PV */ jmp ra,(pv) L_asm_vm_call_method_recompute_pv: lda pv,(asm_vm_call_method - L_asm_vm_call_method_recompute_pv)(ra) mov s0,sp /* restore stack pointer */ L_asm_vm_call_method_recompute_return: ldq ra,0*8(sp) /* restore RA */ ldq gp,1*8(sp) /* restore global pointer */ ldq s0,3*8(sp) lda sp,5*8(sp) /* free stack space */ jmp zero,(ra) asm_vm_call_method_exception_handler: mov s0,sp /* restore stack pointer */ ldq gp,1*8(sp) /* restore global pointer */ mov itmp1,a0 jsr ra,builtin_throw_exception asm_vm_call_method_end: br L_asm_vm_call_method_recompute_return .end asm_vm_call_method /* asm_call_jit_compiler ******************************************************* Invokes the compiler for untranslated Java methods. *******************************************************************************/ .ent asm_call_jit_compiler asm_call_jit_compiler: ldgp gp,0(pv) lda sp,-(ARG_CNT+2)*8(sp) /* +2: keep stack 16-byte aligned */ stq ra,0*8(sp) /* save return address */ SAVE_ARGUMENT_REGISTERS(1) /* save 6 int/6 float argument registers */ mov itmp1,a0 /* pass methodinfo pointer */ mov mptr,a1 /* pass method pointer */ lda a2,(ARG_CNT+2)*8(sp) /* pass java sp */ mov ra,a3 jsr ra,jit_asm_compile /* call jit compiler */ mov v0,pv ldq ra,0*8(sp) /* load return address */ RESTORE_ARGUMENT_REGISTERS(1) /* restore 6 int/6 float argument registers */ lda sp,(ARG_CNT+2)*8(sp) /* remove stack frame */ beq pv,L_asm_call_jit_compiler_exception jmp zero,(pv) /* and call method, the method returns */ /* directly to the caller (ra). */ L_asm_call_jit_compiler_exception: subq sp,2*8,sp stq ra,0*8(sp) /* save return address (xpc) */ jsr ra,exceptions_get_and_clear_exception ldq ra,0*8(sp) /* restore return address (xpc) */ addq sp,2*8,sp mov v0,xptr /* get exception */ subq ra,4,xpc /* exception address is ra - 4 */ br L_asm_handle_nat_exception .end asm_call_jit_compiler /* asm_handle_exception ******************************************************** This function handles an exception. It does not use the usual calling conventions. The exception pointer is passed in REG_ITMP1 and the pc from the exception raising position is passed in REG_ITMP2. It searches the local exception table for a handler. If no one is found, it unwinds stacks and continues searching the callers. ATTENTION: itmp3 == gp! *******************************************************************************/ .ent asm_handle_nat_exception asm_handle_nat_exception: L_asm_handle_nat_exception: /* required for PIC code */ L_asm_handle_exception_stack_loop: lda sp,-6*8(sp) /* keep stack 16-byte aligned */ stq xptr,0*8(sp) /* save xptr */ stq xpc,1*8(sp) /* save xpc */ stq ra,3*8(sp) /* save RA */ stq zero,4*8(sp) /* save maybe-leaf flag (cleared) */ mov ra,a0 /* pass RA */ br ra,L_asm_handle_exception_load_gp L_asm_handle_exception_load_gp: ldgp gp,0(ra) /* load gp */ jsr ra,md_codegen_get_pv_from_pc/* get PV from RA */ stq v0,2*8(sp) /* save PV */ ldq a0,0*8(sp) /* pass xptr */ ldq a1,1*8(sp) /* pass xpc */ mov v0,a2 /* pass PV */ addq sp,6*8,a3 /* pass Java SP */ br L_asm_handle_exception_continue .aent asm_handle_exception asm_handle_exception: L_asm_handle_exception: /* required for PIC code */ lda sp,-(ARG_CNT+TMP_CNT)*8(sp) /* create maybe-leaf stackframe */ SAVE_ARGUMENT_REGISTERS(0) /* we save arg and temp registers in */ SAVE_TEMPORARY_REGISTERS(ARG_CNT) /* case this is a leaf method */ lda sp,-6*8(sp) /* keep stack 16-byte aligned */ stq xptr,0*8(sp) /* save xptr */ stq pv,2*8(sp) /* save PV */ stq ra,3*8(sp) /* save RA */ lda t0,1(zero) /* set maybe-leaf flag */ stq t0,4*8(sp) /* save maybe-leaf flag */ br ra,L_asm_handle_exception_load_gp_2 L_asm_handle_exception_load_gp_2: ldgp gp,0(ra) /* load gp */ mov xptr,a0 /* pass xptr */ mov xpc,a1 /* pass xpc */ mov pv,a2 /* pass PV */ lda a3,(ARG_CNT+TMP_CNT+6)*8(sp)/* pass Java SP */ L_asm_handle_exception_continue: jsr ra,exceptions_handle_exception beq v0,L_asm_handle_exception_not_catched mov v0,xpc /* move handlerpc into xpc */ ldq xptr,0*8(sp) /* restore xptr */ ldq pv,2*8(sp) /* restore PV */ ldq ra,3*8(sp) /* restore RA */ ldq t0,4*8(sp) /* get maybe-leaf flag */ lda sp,6*8(sp) /* free stack frame */ beq t0,L_asm_handle_exception_no_leaf RESTORE_ARGUMENT_REGISTERS(0) /* if this is a leaf method, we have */ RESTORE_TEMPORARY_REGISTERS(ARG_CNT)/* to restore arg and temp registers */ lda sp,(ARG_CNT+TMP_CNT)*8(sp) /* remove maybe-leaf stackframe */ L_asm_handle_exception_no_leaf: jmp zero,(xpc) /* jump to the handler */ L_asm_handle_exception_not_catched: ldq xptr,0*8(sp) /* restore xptr */ ldq pv,2*8(sp) /* restore PV */ ldq ra,3*8(sp) /* restore RA */ ldq t0,4*8(sp) /* get maybe-leaf flag */ lda sp,6*8(sp) beq t0,L_asm_handle_exception_no_leaf_stack lda sp,(ARG_CNT+TMP_CNT)*8(sp) /* remove maybe-leaf stackframe */ mov zero,t0 /* clear the maybe-leaf flag */ L_asm_handle_exception_no_leaf_stack: ldl t1,FrameSize(pv) /* get frame size */ addq t1,sp,t1 /* pointer to save area */ ldl t2,IsLeaf(pv) /* is leaf procedure */ bne t2,L_asm_handle_exception_no_ra_restore ldq ra,-1*8(t1) /* restore ra */ subq t1,8,t1 /* t1-- */ L_asm_handle_exception_no_ra_restore: mov ra,xpc /* the new xpc is ra */ ldl t2,IntSave(pv) /* t2 = saved int register count */ br t3,ex_int1 /* t3 = current pc */ ex_int1: lda t3,(ex_int2 - ex_int1)(t3) negl t2,t2 /* negate register count */ s4addq t2,t3,t3 /* t2 = IntSave - register count * 4 */ jmp zero,(t3) /* jump to save position */ ldq s0,-7*8(t1) ldq s1,-6*8(t1) ldq s2,-5*8(t1) ldq s3,-4*8(t1) ldq s4,-3*8(t1) ldq s5,-2*8(t1) ldq s6,-1*8(t1) ex_int2: s8addq t2,t1,t1 /* t1 = t1 - 8 * register count */ ldl t2,FltSave(pv) /* t2 = saved flt register count */ br t3,ex_flt1 /* t3 = current pc */ ex_flt1: lda t3,(ex_flt2 - ex_flt1)(t3) negl t2,t2 /* negate register count */ s4addq t2,t3,t3 /* t2 = FltSave - 4 * register count */ jmp zero,(t3) /* jump to save position */ ldt fs0,-8*8(t1) ldt fs1,-7*8(t1) ldt fs2,-6*8(t1) ldt fs3,-5*8(t1) ldt fs4,-4*8(t1) ldt fs5,-3*8(t1) ldt fs6,-2*8(t1) ldt fs7,-1*8(t1) ex_flt2: ldl t1,FrameSize(pv) /* get frame size */ addq sp,t1,sp /* unwind stack */ br L_asm_handle_exception_stack_loop .end asm_handle_nat_exception /* asm_abstractmethoderror ***************************************************** Creates and throws an AbstractMethodError. *******************************************************************************/ .ent asm_abstractmethoderror asm_abstractmethoderror: subq sp,2*8,sp /* create stackframe */ stq ra,0*8(sp) /* save return address */ addq sp,2*8,a0 /* pass java sp */ mov ra,a1 /* pass exception address */ jsr ra,exceptions_asm_new_abstractmethoderror ldq ra,0*8(sp) /* restore return address */ addq sp,2*8,sp /* remove stackframe */ mov v0,xptr /* get exception pointer */ subq ra,4,xpc /* exception address is ra - 4 */ br L_asm_handle_nat_exception .end asm_abstractmethoderror /* asm_compare_and_swap ******************************************************** Does an atomic compare and swap. Required for the lock implementation. Atomically do the following: Check if the location still contains `oldval`. If so, replace it by `newval` and return `oldval`. RETURN VALUE: the old value at *p long compare_and_swap(volatile long *p, long oldval, long newval); *******************************************************************************/ .ent asm_compare_and_swap asm_compare_and_swap: 1: ldq_l v0,0(a0) cmpeq v0,a1,t0 beq t0,2f mov a2,t0 stq_c t0,0(a0) beq t0,1b 2: jmp zero,(ra) .end asm_compare_and_swap /* asm_memory_barrier ********************************************************** A memory barrier for the Java Memory Model. *******************************************************************************/ .ent asm_memory_barrier asm_memory_barrier: mb jmp zero,(ra) .end asm_memory_barrier /* asm_md_init ***************************************************************** Initialize machine dependent stuff. Determines if the byte support instruction set (21164a and higher) is available. *******************************************************************************/ .ent asm_md_init asm_md_init: .long 0x47e03c20 /* amask 1,v0 */ jmp zero,(ra) /* return */ .end asm_md_init /* asm_cacheflush ************************************************************** XXX *******************************************************************************/ .ent asm_cacheflush asm_cacheflush: call_pal PAL_imb /* synchronize instruction cache */ jmp zero,(ra) .end asm_cacheflush /* 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: */