/* src/vm/jit/s390/asmpart.S - Java-C interface functions for s390 Copyright (C) 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/s390/arch.h" #include "vm/jit/s390/md-abi.h" #include "vm/jit/s390/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_call_jit_compiler .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 asm_abstractmethoderror: .long 0 asm_builtin_f2i: .long 0 asm_builtin_f2l: .long 0 asm_builtin_d2i: .long 0 asm_builtin_d2l: .long 0 /* Generates a PIC call. * * func: function to call * tag: tag unique for this call to generate a label * tmp: one temporary register needed for calculation * * The offset table used is located at the bottom of this file. * * Note: destroys r12. r12 MUST contain GOT for PIC calls! */ #define CALL_PIC(func, tag) \ bras %r14, L_bras_##tag; /* get PC */ \ L_bras_##tag: \ l %r12, L_offsets - L_bras_##tag (%r14); /* load offset to PLT */ \ la %r12, L_offsets - L_bras_##tag (%r12, %r14); /* load PLT address */ \ l %r14, L_offset_##func - L_bras_##tag (%r14); /* load offset to func */ \ bas %r14, 0(%r14, %r12); /********************* 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); * * * *******************************************************************************/ .long 0 /* catch type all */ .long 0 /* exception handler pc */ .long 0 /* end pc */ .long 0 /* start pc */ .long 1 /* extable size */ .long 0 /* line number table start */ .long 0 /* line number table size */ .long 0 /* fltsave */ .long 0 /* intsave */ .long 0 /* IsLeaf */ .long 0 /* IsSync */ .long 0 /* frame size */ .long 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: ahi sp, -8*4 /* allocate stack frame */ /* a0: PV */ /* a1: data structure */ /* a2: number of stack arguments */ st s0, 0*4(sp) /* store used calle saved registers */ st s1, 1*4(sp) st a0, 2*4(sp) st %r12, 3*4(sp) /* %r12 is callee saved, we'll need it as GOT */ st pv, 4*4(sp) st a4, 5*4(sp) /* a4 is callee saved in terms of C abi */ std ftmp1, 6*4(sp) /* ftmp1 and ftmp2 are callees saved in terms of C abi */ std ftmp2, 8*4(sp) st ra, 10*4(sp) lr s0, a1 /* data structure */ lr %r0, a2 /* number of stack arguments */ l a0, 0*8+4(s0) /* big endian */ l a1, 1*8+4(s0) l a2, 2*8+4(s0) l a3, 3*8+4(s0) l a4, 4*8+4(s0) ld fa0, 5*8(s0) ld fa1, 6*8(s0) lr s1, sp /* backup stack pointer */ ltr %r0, %r0 /* are there any stack arguments ? */ je L_asm_vm_call_method_stack_copy_done lr %r1, %r0 /* copy number of stack arguments */ sll %r1, 3 /* calculate stackframe size */ sr sp, %r1 /* allocate stack frame */ lr %r1, sp /* temporary stack pointer */ L_asm_vm_call_method_stack_copy_loop: mvc 0(8, %r1), 7*8(s0) /* copy argument */ ahi %r1, 8 /* increase sp */ ahi s0, 8 /* set address of next argument */ ahi %r0, -1 /* substract 1 argument */ jh L_asm_vm_call_method_stack_copy_loop L_asm_vm_call_method_stack_copy_done: la mptr, 2*4(s1) /* load method pointer */ l pv, 0(mptr) /* load procedure vector from method pointer */ basr ra, pv /* call method */ lr sp, s1 /* restore stack pointer */ L_asm_vm_call_method_return: l s0, 0*4(sp) /* restore used callee saved registers */ l s1, 1*4(sp) l %r12, 3*4(sp) l pv, 4*4(sp) l a4, 5*4(sp) ld ftmp1, 6*4(sp) ld ftmp2, 8*4(sp) l ra, 10*4(sp) ahi sp, 8*4 /* remove stackframe */ br ra /* return */ asm_vm_call_method_exception_handler: lr a0, xptr ahi sp, -96 CALL_PIC(builtin_throw_exception, avcmeh) ahi sp, 96 j L_asm_vm_call_method_return asm_vm_call_method_end: brc 0,0 /****************** function asm_call_jit_compiler ***************************** * * * invokes the compiler for untranslated JavaVM methods. * * * * itmp3: methodinfo pointer * * itmp1: method pointer * * * *******************************************************************************/ /* argument registers: arguments (like in JIT) arguments on stack (like in JIT) ------------------------------------------------------------- <- SP on entry saved return address \ stored volatile (in terms of C ABI) floag argument registers | 96 stored volatile (in terms of C ABI) integer argument registers | ACJC_STACKFRAME 0 - 96 register save area (C ABI) / -------------------------------------------------- <- SP for jit_asm_compile */ /* This is called from a compiler stub. * Arguments are already in registers and the stack is setup like in CACAO. */ asm_call_jit_compiler: L_asm_call_jit_compiler: # define ACJC_STACKFRAME ((2 * 4) + (4 * 4) + (2 * 8) + 96) ahi sp,-ACJC_STACKFRAME /* allocate stack space */ stm %r2,%r5,96(sp) /* store volatile int arg regs */ std %f0,96+16(sp) /* store volatile float arg regs */ std %f2,96+24(sp) st %r12,96+32(sp) /* store %r12, used as GOT pointer */ st %r14,96+36(sp) /* store return address */ /* load arguments */ lr a0,itmp3 /* pass methodinfo pointer */ lr a1,mptr /* pass method pointer */ la a2,ACJC_STACKFRAME(sp) /* pass java sp */ la a3,0(%r14) /* pass return address, make sure bit 32 is 0 */ CALL_PIC(jit_asm_compile, acjc) lr pv, v0 /* save return value */ lm %r2,%r5,96(sp) /* restore volatile int arg regs */ ld %f0,96+16(sp) /* restore volatile float arg regs */ ld %f2,96+24(sp) /* restore volatile float arg regs */ ltr pv,pv je L_asm_call_jit_compiler_exception l %r12,96+32(sp) /* restore %r12 */ l %r14,96+36(sp) /* restore return address */ ahi sp, ACJC_STACKFRAME /* remove stack frame */ jit_code_entry: /* label to set breakpoint on */ br pv /* call the method, it will return to the caller */ L_asm_call_jit_compiler_exception: CALL_PIC(exceptions_get_and_clear_exception, acjce) lr xptr, %r2 l xpc,96+36(sp) /* restore return address */ l %r12,96+32(sp) /* restore %r12 */ ahi sp, ACJC_STACKFRAME /* remove stack frame */ j L_asm_handle_nat_exception /* 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: L_asm_handle_nat_exception: /* TODO really nothing here ? */ asm_handle_exception: L_asm_handle_exception: /* a wrapper for md_handle_exception */ # define STACKFRAMESIZE (96 + (16 * 4) + (16 * 8) + (4 * 4)) # define REGS 96 # define FREGS (96 + (16 * 4)) # define OUT (96 + (16 * 4) + (16 * 8)) ahi sp, -STACKFRAMESIZE /* allocate stack frame containing the arrays */ /* store special registers to array */ st xptr, REGS+(0*4)(sp) st xpc, REGS+(1*4)(sp) st pv, REGS+(13*4)(sp) la itmp3, STACKFRAMESIZE(sp) st itmp3, REGS+(15*4)(sp) /* store temporary and argument registers */ stm a0, a4, REGS+(2*4)(sp) std %f0, FREGS+(0*8)(sp) std %f1, FREGS+(1*8)(sp) std %f2, FREGS+(2*8)(sp) std %f3, FREGS+(3*8)(sp) std %f5, FREGS+(5*8)(sp) std %f7, FREGS+(7*8)(sp) std %f8, FREGS+(8*8)(sp) std %f9, FREGS+(9*8)(sp) std %f10, FREGS+(10*8)(sp) std %f11, FREGS+(11*8)(sp) std %f12, FREGS+(12*8)(sp) std %f13, FREGS+(13*8)(sp) std %f14, FREGS+(14*8)(sp) std %f15, FREGS+(15*8)(sp) /* store %r12 used as GOT */ st %r12, REGS+(12*4)(sp) /* call md_handle_exception */ la a0, REGS(sp) la a1, FREGS(sp) la a2, OUT(sp) CALL_PIC(md_handle_exception, ahe) /* restore %r12 */ l %r12, REGS+(12*4)(sp) l itmp3, OUT+(2*4)(sp) /* out[2] contains maybe leaf flag */ ltr itmp3, itmp3 je L_restore_saved L_restore_temporary_and_argument: /* if we are maybe leaf, * we have to restore argument and temporary registers */ lm a0, a4, REGS+(2*4)(sp) ld %f0, FREGS+(0*8)(sp) ld %f1, FREGS+(1*8)(sp) ld %f2, FREGS+(2*8)(sp) ld %f3, FREGS+(3*8)(sp) ld %f5, FREGS+(5*8)(sp) ld %f7, FREGS+(7*8)(sp) ld %f8, FREGS+(8*8)(sp) ld %f9, FREGS+(9*8)(sp) ld %f10, FREGS+(10*8)(sp) ld %f11, FREGS+(11*8)(sp) ld %f12, FREGS+(12*8)(sp) ld %f13, FREGS+(13*8)(sp) ld %f14, FREGS+(14*8)(sp) ld %f15, FREGS+(15*8)(sp) j L_restore_done L_restore_saved: /* if we are not a maybe leaf, * we have to restore callee saved registers of the callee */ l itmp3, OUT+(0*4)(sp) /* out[0] contains IntSav */ ahi itmp3, -1 jl L_int_done l s5, REGS+(12*4)(sp) ahi itmp3, -1 jl L_int_done l s4, REGS+(11*4)(sp) ahi itmp3, -1 jl L_int_done l s3, REGS+(10*4)(sp) ahi itmp3, -1 jl L_int_done l s2, REGS+(9*4)(sp) ahi itmp3, -1 jl L_int_done l s1, REGS+(8*4)(sp) ahi itmp3, -1 jl L_int_done l s0, REGS+(7*4)(sp) L_int_done: /* restore callee saved float registers */ /* there are currently none */ L_flt_done: L_restore_done: /* write new values for special registers */ l xptr, REGS+(0*4)(sp) l xpc, REGS+(1*4)(sp) l pv, REGS+(13*4)(sp) l sp, REGS+(15*4)(sp) br xpc /* jump to handler */ # undef STACKFRAMESIZE # undef REGS # undef FREGS # undef OUT #if 0 /* 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 #endif /* Offset table for PIC calls, see CALL_PIC */ L_offsets: .long _GLOBAL_OFFSET_TABLE_ - L_offsets L_offset_builtin_throw_exception: .long builtin_throw_exception@PLTOFF L_offset_jit_asm_compile: .long jit_asm_compile@PLTOFF L_offset_exceptions_get_and_clear_exception: .long exceptions_get_and_clear_exception@PLTOFF L_offset_md_handle_exception: .long md_handle_exception@PLTOFF /* * 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: */