/* src/vm/jit/x86_64/asmpart.S - Java-C interface functions for x86_64 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/x86_64/arch.h" #include "vm/jit/x86_64/md-abi.h" #include "vm/jit/x86_64/md-asm.h" #include "vm/jit/abi-asm.h" #include "vm/jit/methodheader.h" .text /* 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_handle_exception .globl asm_handle_nat_exception .globl asm_abstractmethoderror .globl asm_builtin_f2i .globl asm_builtin_f2l .globl asm_builtin_d2i .globl asm_builtin_d2l .globl asm_compare_and_swap .globl asm_memory_barrier /********************* function asm_calljavafunction *************************** * * * 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_calljavamethod (methodinfo *m, * * void *arg1, void *arg2, void *arg3, void *arg4); * * * *******************************************************************************/ .align 8 .quad 0 /* line number table start */ .quad 0 /* line number table size */ .long 0 /* fltsave */ .long 0 /* intsave */ .long 0 /* isleaf */ .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: sub $(7*8),sp /* keep stack 16-byte aligned */ mov %rbx,0*8(sp) /* %rbx is not a callee saved in cacao*/ mov s0,1*8(sp) mov s1,2*8(sp) mov s2,3*8(sp) mov s3,4*8(sp) mov s4,5*8(sp) mov a0,6*8(sp) /* store method PV */ mov sp,s0 /* save stack pointer */ mov a1,t0 /* address of data structure */ mov a2,itmp1 /* number of stack arguments */ mov 0*8(t0),a0 mov 1*8(t0),a1 mov 2*8(t0),a2 mov 3*8(t0),a3 mov 4*8(t0),a4 mov 5*8(t0),a5 movq 6*8(t0),fa0 movq 7*8(t0),fa1 movq 8*8(t0),fa2 movq 9*8(t0),fa3 movq 10*8(t0),fa4 movq 11*8(t0),fa5 movq 12*8(t0),fa6 movq 13*8(t0),fa7 cmp $0,itmp1l je L_asm_vm_call_method_stack_copy_done mov itmp1,itmp2 add $1,itmp2 /* keep stack 16-byte aligned */ and $0xfffffffffffffffe,itmp2 shl $3,itmp2 /* calculate stack size */ sub itmp2,sp /* create stack frame */ mov sp,itmp2 /* temporary stack pointer */ L_asm_vm_call_method_stack_copy_loop: mov 14*8(t0),itmp3 /* load argument */ mov itmp3,0(itmp2) /* store argument on stack */ sub $1,itmp1l /* subtract 1 argument */ add $8,t0 /* set address of next argument */ add $8,itmp2 /* increase SP */ cmp $0,itmp1l jg L_asm_vm_call_method_stack_copy_loop L_asm_vm_call_method_stack_copy_done: lea (6*8-256)(s0),mptr /* We subtract 256 to force the next */ /* move instruction to have a 32-bit */ /* offset. */ mov (0*8+256)(mptr),itmp3 /* load PV */ call *itmp3 mov s0,sp /* restore SP */ L_asm_vm_call_method_return: mov 0*8(sp),%rbx /* restore callee saved registers */ mov 1*8(sp),s0 mov 2*8(sp),s1 mov 3*8(sp),s2 mov 4*8(sp),s3 mov 5*8(sp),s4 add $(7*8),sp /* free stack space */ ret asm_vm_call_method_exception_handler: mov xptr,a0 /* pass exception pointer */ call builtin_throw_exception@PLT jmp L_asm_vm_call_method_return asm_vm_call_method_end: nop /* 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. * * * *******************************************************************************/ asm_handle_nat_exception: add $8,sp /* clear return address of native stub*/ asm_handle_exception: L_asm_handle_exception: /* required for PIC code */ sub $((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 */ mov $((ARG_CNT+TMP_CNT)*8),a3 /* prepare a3 for handle_exception */ mov $1,t0 /* set maybe-leaf flag */ L_asm_handle_exception_stack_loop: sub $(6*8),sp mov xptr,0*8(sp) /* save exception pointer */ mov xpc,1*8(sp) /* save exception pc */ add sp,a3 /* calculate Java sp into a3... */ add $(6*8),a3 mov a3,3*8(sp) /* ...and save it */ mov t0,4*8(sp) /* save maybe-leaf flag */ mov xpc,a0 /* exception pc */ call codegen_get_pv_from_pc@PLT mov v0,2*8(sp) /* save data segment pointer */ mov 0*8(sp),a0 /* pass exception pointer */ mov 1*8(sp),a1 /* pass exception pc */ mov v0,a2 /* pass data segment pointer */ mov 3*8(sp),a3 /* pass Java stack pointer */ call exceptions_handle_exception@PLT test v0,v0 jz L_asm_handle_exception_not_catched mov v0,xpc /* move handlerpc into xpc */ mov 0*8(sp),xptr /* restore exception pointer */ mov 4*8(sp),t0 /* get maybe-leaf flag */ add $(6*8),sp /* free stack frame */ test t0,t0 /* test for maybe-leaf flag */ jz 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 */ add $((ARG_CNT+TMP_CNT)*8),sp /* remove maybe-leaf stackframe */ L_asm_handle_exception_no_leaf: jmp *xpc /* jump to the handler */ L_asm_handle_exception_not_catched: mov 0*8(sp),xptr /* restore exception pointer */ mov 2*8(sp),itmp3 /* restore data segment pointer */ mov 4*8(sp),t0 /* get maybe-leaf flag */ add $(6*8),sp test t0,t0 jz L_asm_handle_exception_no_leaf_stack add $((ARG_CNT+TMP_CNT)*8),sp /* remove maybe-leaf stackframe */ xor t0,t0 /* clear the isleaf flags */ L_asm_handle_exception_no_leaf_stack: mov FrameSize(itmp3),itmp2l /* get frame size */ add sp,itmp2 /* pointer to save area */ mov IntSave(itmp3),a0l /* a0l = saved int register count */ test a0l,a0l je noint cmp $1,a0l je int1 cmp $2,a0l je int2 cmp $3,a0l je int3 cmp $4,a0l je int4 mov -5*8(itmp2),s0 int4: mov -4*8(itmp2),s1 int3: mov -3*8(itmp2),s2 int2: mov -2*8(itmp2),s3 int1: mov -1*8(itmp2),s4 shl $3,a0l /* multiply by 8 bytes */ sub a0,itmp2 noint: #if 0 mov FltSave(itmp3),a0l /* a0l = saved flt register count */ test a0l,a0l je noflt cmpl $1,a0l je flt1 cmpl $2,a0l je flt2 cmpl $3,a0l je flt3 cmpl $4,a0l je flt4 movq -5*8(itmp2),%xmm11 flt4: movq -4*8(itmp2),%xmm12 flt3: movq -3*8(itmp2),%xmm13 flt2: movq -2*8(itmp2),%xmm14 flt1: movq -1*8(itmp2),%xmm15 noflt: #endif mov FrameSize(itmp3),itmp2l /* get frame size */ add itmp2,sp /* unwind stack */ /* exception pointer is still set */ pop xpc /* the new xpc is return address */ sub $3,xpc /* subtract 3 bytes for call */ xor a3,a3 /* prepare a3 for handle_exception */ jmp L_asm_handle_exception_stack_loop /* asm_abstractmethoderror ***************************************************** Creates and throws an AbstractMethodError. *******************************************************************************/ asm_abstractmethoderror: mov sp,a0 /* pass java sp */ add $1*8,a0 mov 0*8(sp),a1 /* pass exception address */ sub $3,a1 call exceptions_asm_new_abstractmethoderror@PLT /* exception pointer is return value */ pop xpc /* get exception address */ sub $3,xpc /* exception address is ra - 3 */ jmp L_asm_handle_exception /* asm_builtin_x2x ************************************************************* * * * Wrapper functions for float to int corner cases * * * *******************************************************************************/ asm_builtin_f2i: sub $(ARG_CNT*8),sp SAVE_ARGUMENT_REGISTERS(0) movq ftmp1,fa0 call builtin_f2i@PLT RESTORE_ARGUMENT_REGISTERS(0) add $(ARG_CNT*8),sp ret asm_builtin_f2l: sub $(ARG_CNT*8),sp SAVE_ARGUMENT_REGISTERS(0) movq ftmp1,fa0 call builtin_f2l@PLT RESTORE_ARGUMENT_REGISTERS(0) add $(ARG_CNT*8),sp ret asm_builtin_d2i: sub $(ARG_CNT*8),sp SAVE_ARGUMENT_REGISTERS(0) movq ftmp1,fa0 call builtin_d2i@PLT RESTORE_ARGUMENT_REGISTERS(0) add $(ARG_CNT*8),sp ret asm_builtin_d2l: sub $(ARG_CNT*8),sp SAVE_ARGUMENT_REGISTERS(0) movq ftmp1,fa0 call builtin_d2l@PLT RESTORE_ARGUMENT_REGISTERS(0) add $(ARG_CNT*8),sp ret /* asm_compare_and_swap ******************************************************** Does an atomic compare and swap. Required for the lock implementation. *******************************************************************************/ asm_compare_and_swap: mov a1,v0 /* v0 is %rax */ lock cmpxchg a2,(a0) ret /* asm_memory_barrier ********************************************************** A memory barrier for the Java Memory Model. *******************************************************************************/ asm_memory_barrier: mfence ret /* 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: */