/* src/vm/jit/arm/asmpart.S - Java-C interface functions for ARM 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 #include "vm/jit/arm/md-asm.h" #include "vm/jit/methodheader.h" .file "asmpart.S" .text .align 2 /* 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_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. *******************************************************************************/ .align 2 .word 0 /* FltSave */ .word 0 /* IntSave */ .word 0 /* IsLeaf */ .word 0 /* FrameSize */ .word 0 /* CodeinfoPointer */ 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_SCRATCH_REGISTERS /* save our personal scratch regs */ stmfd sp!, {v1} /* V1 is used to remember SP */ str a0, [sp, #-4]! /* store methods entrypoint */ mov v1, sp /* remember SP */ mov itmp1, a1 /* address of data structure */ mov itmp3, a2 /* stack argument count */ ldr a0, [itmp1], #8 /* load argument registers */ ldr a1, [itmp1], #8 ldr a2, [itmp1], #8 ldr a3, [itmp1], #8 cmp itmp3, #0 /* do we have stack arguments? */ ble asm_calljava_copyfinish /* no -> do not care :-) */ mov itmp2, #0 sub sp, sp, itmp3, lsl #3 /* create stackframe for arguments */ asm_calljava_copyloop: /* reorder stack arguments! */ ldr ip, [itmp1], #4 /* load argument */ str ip, [sp, itmp2] /* store argument on stack */ add itmp2, itmp2, #4 /* next stackslot */ ldr ip, [itmp1], #4 /* load argument */ str ip, [sp, itmp2] /* store argument on stack */ add itmp2, itmp2, #4 /* next stackslot */ subs itmp3, itmp3, #1 /* next argument */ bgt asm_calljava_copyloop asm_calljava_copyfinish: mov mptr, v1 /* set method pointer */ /* REMEMBER: do the method call just like in java! */ ldr ip, [mptr] /* fake virtual function call */ mov lr, pc mov pc, ip fake: sub ip, pc, #(fake - asm_vm_call_method)+8 mov sp, v1 /* restore SP */ add sp, sp, #4 /* free fake address */ ldmfd sp!, {v1} RESTORE_SCRATCH_REGS_AND_RETURN /* return to caller, restore regs */ asm_vm_call_method_exception_handler: mov a0, xptr /* exception pointer is arg1 */ bl builtin_throw_exception /* throw the exception */ mov res1, #0 /* return NULL */ mov res2, #0 /* return NULL */ mov sp, v1 /* restore SP */ add sp, sp, #4 /* free fake address */ ldmfd sp!, {v1} RESTORE_SCRATCH_REGS_AND_RETURN /* return to caller, restore regs */ asm_vm_call_method_float: mov a0,#0x51 b asm_debug asm_vm_call_method_double: mov a0,#0x52 b asm_debug asm_vm_call_method_end: /****************** function asm_call_jit_compiler ***************************** * * * Invokes the compiler for untranslated JavaVM methods. * * What this method does: * * - save args and LR * * - fire up jit_compile (pass methodinfo pointer) * * - try to find out where to write back the new method pointer * * - restore args and LR * * - check for exceptions * * - eventually write back new method pointer * * - call jit code (wich will then return to caller) * * * * These methods can call us: codegen_compilerstub & asm_calljavafunction * * ATTENTION: use REG_ITMP1 to pass methodinfo pointer to me! * * * *******************************************************************************/ #define MYSTACKSIZE (6*4) asm_call_jit_compiler: SAVE_ARGUMENT_REGISTERS /* save our argument registers & LR */ sub sp, sp, #4 /* keep stack 8-byte aligned */ mov a0, itmp1 /* pass methodinfo pointer */ mov a1, mptr /* pass method pointer */ add a2, sp, #MYSTACKSIZE /* pass Java sp */ mov a3, lr /* pass Java RA (correct for leafs) */ bl jit_asm_compile mov itmp1, res1 /* save pointer to new jit-code */ tst itmp1,itmp1 /* check for exeption */ beq L_asm_call_jit_compiler_exception add sp, sp, #4 /* keep stack 8-byte aligned */ RESTORE_ARGUMENT_REGISTERS /* load our argument registers & LR */ mov ip, itmp1 mov pc, ip /* call jit-code */ L_asm_call_jit_compiler_exception: bl exceptions_get_and_clear_exception mov xptr, res1 /* get exception */ add sp, sp, #4 /* keep stack 8-byte aligned */ RESTORE_ARGUMENT_REGISTERS /* load LR */ sub xpc, lr, #4 /* xpc = instruction that called us */ b asm_handle_nat_exception /********************* function 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. * * * * void asm_handle_exception (exceptionptr, exceptionpc); * * * *******************************************************************************/ asm_handle_nat_exception: /*TODO:maybe make a macro out of it!!!*/ SAVE_ARGUMENT_REGISTERS mov a0, lr bl md_asm_codegen_get_pv_from_pc mov ip, res1 RESTORE_ARGUMENT_REGISTERS /* fall through */ asm_handle_exception: stmfd sp!, {r0 - r3} /* save possible used registers */ mov itmp3, #1 /* set maybe-leaf flag */ mov a3, #(4*4) /* prepare a3 for handle_exception */ asm_handle_exception_loop: stmfd sp!, {ip,lr} /* call exception helper here! */ mov a0, xptr /* pass exception pointer */ mov a1, xpc /* pass exception pointer */ mov a2, ip /* pass data segment pointer */ add a3, sp, a3 /* calculate Java sp into a3... */ add a3, a3, #(2*4) bl exceptions_handle_exception ldmfd sp!, {ip,lr} tst a0, a0 beq asm_handle_exception_not_catched mov xpc, a0 /* move handlerpc into xpc */ tst itmp3,itmp3 /* if this is a lead method ... */ ldmnefd sp!, {r0 - r3} /* restore argument registers */ mov pc, xpc /* jump to handler */ asm_handle_exception_not_catched: tst itmp3,itmp3 /* if this is a lead method ... */ addne sp, sp, #(4*4) /* remove maybe-leaf stackframe */ movne itmp3, #0 /* remove maybe-leaf flag */ ldr a2, [ip, #FrameSize] /* t2 = frame size */ add a0, sp, a2 /* t0 = pointer to save area */ ldr a1, [ip, #IsLeaf] /* t1 = is leaf procedure */ tst a1, a1 /* if is leaf ... */ ldreq lr, [a0, #-4]! /* ... restore RA */ mov xpc, lr /* the new xpc is RA */ ldr a1, [ip, #IntSave] /* t1 = saved int register count */ rsb a1, a1, #5 /* t1 = count of unsaved registers */ sub a1, a1, #1 add pc, pc, a1, lsl #2 /* do not load unsaved registers */ ldr v1, [a0, #-20] /* ... but restore the other ones */ ldr v2, [a0, #-16] ldr v3, [a0, #-12] ldr v4, [a0, #- 8] ldr v5, [a0, #- 4] add sp, sp, a2 /* unwind stack (using t2) */ mov a3, #0 /* prepare a3 for handle_exception */ /*TODO:maybe make a macro out of it!!!*/ SAVE_ARGUMENT_REGISTERS mov a0, lr bl md_asm_codegen_get_pv_from_pc mov ip, res1 RESTORE_ARGUMENT_REGISTERS b asm_handle_exception_loop /* asm_abstractmethoderror ***************************************************** Creates and throws an AbstractMethodError. *******************************************************************************/ asm_abstractmethoderror: stmfd sp!, {lr} /* save return address */ add a0, sp, #(1*4) /* pass java sp */ mov a1, lr /* pass exception address */ bl exceptions_asm_new_abstractmethoderror ldmfd sp!, {lr} /* restore return address */ mov xptr, res1 /* get exception pointer */ sub xpc, lr, #4 /* exception address is ra - 4 */ b asm_handle_nat_exception /********************* function asm_cacheflush ********************************* * * * TODO: document me * * * * void asm_cacheflush(void *p, s4 size); * * * *******************************************************************************/ .equ sys_cacheflush,__ARM_NR_cacheflush /* syscall number for cache flushing */ asm_cacheflush: add a1, a0, a1 mov a2, #0 #if defined(__ARM_EABI__) /* According to EABI, the syscall number should be passed via R7, see "http://wiki.debian.org/ArmEabiPort" for additional details. */ stmfd sp!, {r7} mov r7, #0x0f0000 add r7, r7, #0x000002 #endif #if 0 /* TWISTI: required on iyonix, maybe a linux-2.4 bug */ mov a0, #0x0 mov a1, #0xff000000 #endif swi sys_cacheflush #if defined(__ARM_EABI__) ldmfd sp!, {r7} #endif mov pc, lr /* 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: */