Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- $Id: asmpart.S 7661 2007-04-03 22:29:59Z twisti $
-
*/
#include "vm/jit/s390/arch.h"
#include "vm/jit/s390/md-abi.h"
#include "vm/jit/s390/md-asm.h"
-#include "vm/jit/s390/offsets.h"
#include "vm/jit/abi-asm.h"
#include "vm/jit/methodheader.h"
-/* Copy a call to a PIC function from gcc -S
- * We setup a temporary literal pool pointer.
- */
-
-#define PIC_CALL(fun, magic) \
- bras itmp3, L_##magic##_lp_end ; \
-L_##magic##_lp: ; \
-L_##magic##_lp_5: ; \
- .long fun@PLTOFF ; \
-L_##magic##_lp_4: ; \
- .long _GLOBAL_OFFSET_TABLE_-L_##magic##_lp ; \
-L_##magic##_lp_end: ; \
- l itmp2,L_##magic##_lp_4-L_##magic##_lp(itmp3) ; \
- la itmp2,0(itmp2,itmp3) ; \
- l itmp1,L_##magic##_lp_5-L_##magic##_lp(itmp3) ; \
- bas %r14,0(itmp1,itmp2)
-
.text
.globl asm_abstractmethoderror
- .globl asm_patcher_wrapper
-
.globl asm_replacement_out
.globl asm_replacement_in
.globl asm_builtin_d2i
.globl asm_builtin_d2l
- .globl asm_criticalsections
- .globl asm_getclassvalues_atomic
-
asm_abstractmethoderror:
.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/itmp2. 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) *
asm_vm_call_method_float:
asm_vm_call_method_double:
-/*
-
-a0: methodinfo *m
-a1: s4 vmargscount ---> v0: java_objectheader *
-a2: vm_arg *vmargs
-r14: return address
-
-96 ... on stack parameters (none)
-0 - 96 register save area
--------------------------------------------------- <- SP on asm_vm_... entry
- local variables
- saved return address (important to be at 0(sp) because of md_stacktrace_get_returnaddress)
------------------------------------------ <- SP after stack frame allocation
- arguments on stack
----------------------------------------------------- <- SP on JIT code entry
- saved return address (callee saved)
-
-*/
-
-
-/*
- Regiser usage:
- itmp1: argument block pointer
- itmp2: argument counter
- s0: integer argument counter
- s1: float argument counter
- s2: integer register counter
- s3: backup argument block pointer
- s4: backup argument count
-*/
-
- stm %r6, %r15, 24(sp) /* save callers regiters */
- stm a0, a2, 8(sp) /* save arguments */
- ahi sp, -8 /* allocate stack space for local variables */
- st %r14, 0(sp) /* store RA once more at bottom of stack frame */
-
- ltr a1, a1 /* maybe we have no args... */
- je L_no_args
-
- lr itmp2, a1 /* load arg count */
- lr itmp1, a2 /* load arg pointer */
-
- ahi itmp1, -sizevmarg /* initialize arg pointer */
- ahi itmp2, 1 /* initialize arg count */
- lhi s0, 0 /* initialize integer arg counter */
- lhi s2, 0 /* initialize integer register counter */
- lhi s1, 0 /* initialize float arg counter */
-
- lr s4, a1 /* backup arg count */
- lr s3, a2 /* backup arg pointer */
-
-L_register_copy:
-
- ahi itmp1, sizevmarg /* forward arg pointer */
- ahi itmp2, -1 /* decrement arg count */
- je L_register_copy_done /* no arguments left */
-
- tm offvmargtype(itmp1), 0x02 /* is this a float/double type? */
- jne L_register_handle_float
-
-L_register_handle_int:
-
- chi s2, INT_ARG_CNT /* are we out of integer arg registers ? */
- je L_register_copy /* yes, next loop */
-
- tm offvmargtype(itmp1), 0x01 /* is this a 2 word type ? */
- jne L_register_handle_long
-
- ahi s0, 1 /* increment integer arg counter */
- ahi s2, 1 /* increment integer register counter */
-
- /* handle argument */
-
- chi s2, 1
- je L_handle_i0
- chi s2, 2
- je L_handle_i1
- chi s2, 3
- je L_handle_i2
- chi s2, 4
- je L_handle_i3
- chi s2, 5
- je L_handle_i4
-
-L_register_handle_long:
-
- chi s2, (INT_ARG_CNT - 1) /* are there 2 integer arg registers left ? */
- jl L_register_handle_long_continue /* yes */
- lhi s2, INT_ARG_CNT /* no, drop last register */
- j L_register_copy
-
-L_register_handle_long_continue:
-
- ahi s0, 1 /* increment integer arg counter */
- ahi s2, 2 /* consume 2 integer arg registers */
-
- /* handle argument */
-
- chi s2, 1
- je L_handle_l0
- chi s2, 2
- je L_handle_l1
- chi s2, 3
- je L_handle_l2
- chi s2, 4
- je L_handle_l3
-
-L_register_handle_float:
-
- chi s1, FLT_ARG_CNT /* are we out of float arg registers */
- je L_register_copy /* no arg regisers left */
-
- ahi s1, 1 /* increment float argument counter */
-
- tm offvmargtype(itmp1), 0x01 /* is this a 2 word type ? */
- jne L_register_handle_double
-
- /* handle argument */
-
- chi s1, 1
- je L_handle_f0
- chi s1, 2
- je L_handle_f1
-
-L_register_handle_double:
-
- /* handle argument */
-
- chi s1, 1
- je L_handle_d0
- chi s1, 2
- je L_handle_d1
-
-L_register_copy_done:
-
-/*
- Regiser usage:
- itmp1: argument block pointer
- itmp2: argument counter
- s0: integer argument counter (initialized by previous code)
- s1: float argument counter (initialized by previous code)
- s2: pointer to current argument on stack
- s3: backup argument block pointer (used to initialize itmp1)
- after used as backup of original stack pointer
- s4: backup argument count (used to initialize itmp2)
- after used as size of parameters on stack
-*/
-
- lr itmp2, s4 /* restore argument counter */
- lr itmp1, s3 /* restore argument block pointer */
-
- /* calculate remaining arguments */
- sr s4, s0 /* - integer arguments in registers */
- sr s4, s1 /* - float arguments in registers */
-
- lr s3, sp /* backup stack pointer (does not alter CC) */
-
- je L_copy_done /* no arguments left for stack */
-
- sll s4, 3 /* allocate 8 bytes per parameter on stack */
- sr sp, s4 /* allocate stack space for arguments */
-
- lr s2, sp /* points now to current argument on stack */
-
- ahi itmp1, -sizevmarg /* initialize argument block pointer */
- ahi itmp2, 1 /* initialize argument counter */
-
-L_stack_copy_loop:
-
- ahi itmp1, sizevmarg /* forward argument block pointer */
- ahi itmp2, -1 /* decrement argument counter */
- je L_copy_done /* all arguments done */
-
- tm offvmargtype(itmp1), 0x0 /* is this a float/double type? */
- jne L_stack_handle_float
-
-L_stack_handle_int:
-
- ahi s0, -1 /* decrement number of integer arguments in regs */
- jhe L_stack_copy_loop /* argument is in register */
-
- tm offvmargtype(itmp1), 0x01 /* is this a 2 word type ? */
- jne L_stack_handle_long
-
- mvc 0(4, s2), offvmargdata+4(itmp1) /* copy integer value */
- ahi s2, 4
- j L_stack_copy_loop
-
-L_stack_handle_long:
-
- mvc 0(8, s2), offvmargdata(itmp1) /* copy long value */
- ahi s2, 8
- j L_stack_copy_loop
-
-L_stack_handle_float:
+ ahi sp, -8*4 /* allocate stack frame */
- ahi s1, -1 /* decrement number of float arguments in regs */
- jhe L_stack_copy_loop /* argument is in register */
+ /* a0: PV */
+ /* a1: data structure */
+ /* a2: number of stack arguments */
- tm offvmargtype(itmp1), 0x01 /* is this a 2 word type ? */
- jne L_stack_handle_double
+ st s0, 0*4(sp) /* store used calle saved registers */
+ st s1, 1*4(sp)
+ st a0, 2*4(sp)
+ st mptr, 3*4(sp) /* mptr/itmp2 is callee saved in terms of C abi */
+ st pv, 4*4(sp)
+ st a4, 5*4(sp) /* a4 is callee saved in terms of C abi */
+ st ra, 6*4(sp)
- mvc 0(4, s2), offvmargdata(itmp1) /* copy float value */
- ahi s2, 4
- j L_stack_copy_loop
+ lr s0, a1 /* data structure */
+ lr %r0, a2 /* number of stack arguments */
-L_stack_handle_double:
+ 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)
- mvc 0(8, s2), offvmargdata(itmp1) /* copy double value */
- ahi s2, 8
- j L_stack_copy_loop
+ ld fa0, 5*8(s0)
+ ld fa1, 6*8(s0)
-L_copy_done:
+ lr s1, sp /* backup stack pointer */
- /* Now we call the compiler in a rather questionable way i needed
- * some days to understand:
- *
- * We can't simply call asm_call_jit_compiler, but we have to call an
- * address loaded from memory like it is done in JIT code.
- *
- * This is because the compiler will intercept the instruction before
- * the call instruction, extract the address where the function pointer
- * has been loaded from and overwrite it with the code entry.
- *
- * Arguments are passed in temporary registers.
- */
+ 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 */
- /* load address of L_asm_call_jit_compiler into memory */
+L_asm_vm_call_method_stack_copy_loop:
- basr mptr, 0 /* store PC */
-L_basr:
- la mptr, L_asm_call_jit_compiler-L_basr(mptr) /* add offset to PC */
- st mptr, 4(s3) /* store on stack */
+ 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 itmp1, 8+8(s3) /* load methodinfo for compiler */
- la mptr, 4(s3) /* store **function in mptr for compiler */
+L_asm_vm_call_method_stack_copy_done:
- /* call L_asm_call_jit_compiler like JIT code would do */
+ 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 itmp3, 0(mptr) /* load address of target from memory */
- basr %r14, itmp3 /* jump to target */
+L_asm_vm_call_method_return:
- /* todo will s4 survive the call? */
- ar sp, s4 /* remove stack space for arguments */
+ l s0, 0*4(sp) /* restore used callee saved registers */
+ l s1, 1*4(sp)
+ l mptr, 3*4(sp)
+ l pv, 4*4(sp)
+ l a4, 5*4(sp)
+ l ra, 6*4(sp)
-L_asm_vm_call_method_return:
+ ahi sp, 8*4 /* remove stackframe */
+ br ra /* return */
- ahi sp, 8 /* remove stack space for local variables */
- lm %r6, %r15, 24(sp) /* restore callers registers */
- br %r14 /* return */
asm_vm_call_method_exception_handler:
lr a0, xptr
- bras %r14, L_avcmeh_bras
- .long builtin_throw_exception
-L_avcmeh_bras:
- l %r14, 0(%r14)
ahi sp, -96
- basr %r14, %r14
+ CALL_PIC(builtin_throw_exception, avcmeh)
ahi sp, 96
j L_asm_vm_call_method_return
-/* .... */
-
-L_no_args:
- lr s3, sp
- lhi s4, 0
- j L_copy_done
-
-L_handle_i0:
- l a0, offvmargdata+4(itmp1)
- j L_register_copy
-L_handle_i1:
- l a1, offvmargdata+4(itmp1)
- j L_register_copy
-L_handle_i2:
- l a2, offvmargdata+4(itmp1)
- j L_register_copy
-L_handle_i3:
- l a3, offvmargdata+4(itmp1)
- j L_register_copy
-L_handle_i4:
- l a4, offvmargdata+4(itmp1)
- j L_register_copy
-
-L_handle_l0:
- lm a0, a1, offvmargdata(itmp1)
- j L_register_copy
-L_handle_l1:
- lm a1, a2, offvmargdata(itmp1)
- j L_register_copy
-L_handle_l2:
- lm a2, a3, offvmargdata(itmp1)
- j L_register_copy
-L_handle_l3:
- lm a3, a4, offvmargdata(itmp1)
- j L_register_copy
-
-L_handle_f0:
- le fa0, offvmargdata(itmp1)
- j L_register_copy
-L_handle_f1:
- le fa1, offvmargdata(itmp1)
- j L_register_copy
-
-L_handle_d0:
- ld fa0, offvmargdata(itmp1)
- j L_register_copy
-L_handle_d1:
- ld fa1, offvmargdata(itmp1)
- j L_register_copy
-
asm_vm_call_method_end:
- nop
+ brc 0,0
/****************** function asm_call_jit_compiler *****************************
* *
asm_call_jit_compiler:
L_asm_call_jit_compiler:
-# define ACJC_STACKFRAME (4 + (4 * 4) + (2 * 8) + 96)
+# define ACJC_STACKFRAME (4 + (4 * 4) + (2 * 8) + 96 + 4)
ahi sp,-ACJC_STACKFRAME /* allocate stack space */
la a2,ACJC_STACKFRAME(sp) /* pass java sp */
la a3,0(%r14) /* pass return address, make sure bit 32 is 0 */
- /* call jit_asm_compile in a PIC way */
-
- bras itmp2, L_bras_jac
- .long jit_asm_compile
-L_bras_jac:
- l itmp2, 0(itmp2)
- basr %r14, itmp2
+ CALL_PIC(jit_asm_compile, acjc)
lr pv, v0 /* save return value */
L_asm_call_jit_compiler_exception:
- bras itmp2, L_bras_acjce
- .long exceptions_get_and_clear_exception
-L_bras_acjce:
- l itmp2, 0(itmp2)
- basr %r14, itmp2
+
+ CALL_PIC(exceptions_get_and_clear_exception, acjce)
+
lr xptr, %r2
l xpc,96+32(sp) /* restore return address */
ahi sp, ACJC_STACKFRAME /* remove stack frame */
j L_asm_handle_nat_exception
-#if 0
/* asm_handle_exception ********************************************************
* *
* This function handles an exception. It does not use the usual calling *
* *
*******************************************************************************/
-#endif
-
asm_handle_nat_exception:
L_asm_handle_nat_exception:
/* TODO really nothing here ? */
asm_handle_exception:
-L_asm_handle_exception: /* required for PIC code */
-
- ahi sp, -(ARGUMENT_REGISTERS_SIZE + TEMPORARY_REGISTERS_SIZE) /* create maybe-leaf stackframe */
- STORE_ARGUMENT_REGISTERS(0)
- STORE_TEMPORARY_REGISTERS(ARGUMENT_REGISTERS_SIZE)
- lhi a3, (ARGUMENT_REGISTERS_SIZE + TEMPORARY_REGISTERS_SIZE) /* prepare a3 for handle_exception */
-
- lhi %r0, 1 /* set maybe-leaf flag */
-
-L_asm_handle_exception_stack_loop:
- ahi sp,-(6*4)
- st xptr,0*4(sp) /* save exception pointer */
- st xpc,1*4(sp) /* save exception pc */
- la a3,(6*4)(a3,sp) /* calculate Java sp into a3... */
- st a3,3*4(sp) /* ...and save it */
- st %r0,4*4(sp) /* save maybe-leaf flag */
-
- lr a0,xpc /* exception pc */
-
- ahi sp,-96 /* add register save area for C code */
-
- bras %r14,L_ahe_bras /* call codegen_get_pv_from_pc */
- .long codegen_get_pv_from_pc
-L_ahe_bras:
- l %r14,0(%r14)
- basr %r14,%r14
- st v0,2*4+96(sp) /* save data segment pointer */
-
- lr a2,v0 /* pass data segment pointer */
- l a0,0*4+96(sp) /* pass exception pointer */
- l a1,1*4+96(sp) /* pass exception pc */
- l a3,3*4+96(sp) /* pass Java stack pointer */
-
- bras %r14,L_ahe_bras2 /* call exceptions_handle_exception */
- .long exceptions_handle_exception
-L_ahe_bras2:
- l %r14,0(%r14)
- basr %r14,%r14
-
- ahi sp,96 /* remove regiser save area for C code */
-
- ltr v0,v0
- jz L_asm_handle_exception_not_catched
-
- lr xpc,v0 /* move handlerpc into xpc */
- l xptr,0*4(sp) /* restore exception pointer */
- l %r0,4*4(sp) /* get maybe-leaf flag */
- ahi sp,(6*4) /* free stack frame */
-
- ltr %r0, %r0
- jz L_asm_handle_exception_no_leaf
-
- LOAD_ARGUMENT_REGISTERS(0)
- LOAD_TEMPORARY_REGISTERS(ARGUMENT_REGISTERS_SIZE)
-
- ahi sp, (ARGUMENT_REGISTERS_SIZE + TEMPORARY_REGISTERS_SIZE) /* Remove maybe-leaf stackframe */
-
-L_asm_handle_exception_no_leaf:
- br xpc /* jump to the handler */
-
-L_asm_handle_exception_not_catched:
- l xptr,0*4(sp) /* restore exception pointer */
- l itmp3,2*4(sp) /* restore data segment pointer */
- ahi itmp3,-0xfff /* for negative displacements */
- l %r0,4*4(sp) /* get maybe-leaf flag */
- ahi sp,(6*4)
-
- ltr %r0,%r0
- jz L_asm_handle_exception_no_leaf_stack
-
- ahi sp, (ARGUMENT_REGISTERS_SIZE + TEMPORARY_REGISTERS_SIZE) /* Remove maybe-leaf stackframe */
- lhi %r0,0 /* clear the isleaf flags */
-
- /*
- +-----------------+-----------+---------+----+
- | Memuse | Float Sav | Int Sav | RA |
- | | 0 ... n | 0 ... n | |
- +-----------------+-----------+---------+----+
- ^ ^ ^
- SP F I
- */
-
-L_asm_handle_exception_no_leaf_stack:
-
- l itmp2,0xfff+FrameSize(itmp3)/* get frame size */
- la itmp2,0(itmp2,sp) /* pointer to save area */
- ahi itmp2,-4 /* skip RA */
-
- l a0,0xfff+IntSave(itmp3) /* a0 = saved int register count */
-
- ltr a0,a0
- je noint
-
- sll a0,2 /* a0 = saved int register count * 4 */
- sr itmp2, a0 /* skip Int Sav */
-
- chi a0,1*4
- je int1
- chi a0,2*4
- je int2
- chi a0,3*4
- je int3
- chi a0,4*4
- je int4
-
- l s0,0*4(itmp2)
-int4:
- l s1,1*4(itmp2)
-int3:
- l s2,2*4(itmp2)
-int2:
- l s3,3*4(itmp2)
-int1:
- l s4,4*4(itmp2)
-
-noint:
-
- l a0,0xfff+FltSave(itmp3)
- ltr a0,a0 /* Number of saved floating point registers */
- je noflt
-
- sll a0,3 /* Number of saved floating point registers * 8 */
- sr itmp2,a0
-
- chi a0,1*8
- je flt1
- chi a0,2*8
- je flt2
-
-flt2:
- ld %f6,1*8(itmp2)
-flt1:
- ld %f4,0*8(itmp2)
-
-noflt:
-
- l itmp3,0xfff+FrameSize(itmp3)/* get frame size (at least 4 - RA) */
- ahi itmp3,-4 /* substract 4 */
- l xpc,0(itmp3,sp) /* load the new xpc - return address */
- la sp, 4(itmp3,sp) /* unwind stack */
-
- /* exception pointer is still set */
-#if 0
- sub $3,xpc /* subtract 3 bytes for call */
-#endif
+L_asm_handle_exception:
- lhi a3,0 /* prepare a3 for handle_exception */
-
- j L_asm_handle_exception_stack_loop
+ /* 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))
-#if 0
+ ahi sp, -STACKFRAMESIZE /* allocate stack frame containing the arrays */
-/* asm_abstractmethoderror *****************************************************
+ /* store special registers to array */
- Creates and throws an AbstractMethodError.
+ st xptr, REGS+(1*4)(sp)
+ st xpc, REGS+(12*4)(sp)
+ st pv, REGS+(13*4)(sp)
+ la itmp3, STACKFRAMESIZE(sp)
+ st itmp3, REGS+(15*4)(sp)
-*******************************************************************************/
+ /* store temporary and argument registers */
-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
+ 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)
-/* asm_patcher_wrapper *********************************************************
+ /* call md_handle_exception */
- XXX
+ la a0, REGS(sp)
+ la a1, FREGS(sp)
+ la a2, OUT(sp)
- Stack layout:
- 20 return address into JIT code (patch position)
- 16 pointer to virtual java_objectheader
- 12 machine code (which is patched back later)
- 8 unresolved class/method/field reference
- 4 data segment displacement from load instructions
- 0 patcher function pointer to call (pv afterwards)
+ CALL_PIC(md_handle_exception, ahe)
-*******************************************************************************/
+ l itmp3, OUT+(2*4)(sp) /* out[2] contains maybe leaf flag */
+ ltr itmp3, itmp3
+ je L_restore_saved
-asm_patcher_wrapper:
-# define apw_sfs (96 + 4 + VOLATILE_INTEGER_REGISTERS_SIZE + VOLATILE_FLOAT_REGISTERS_SIZE)
+L_restore_temporary_and_argument:
- ahi sp, -apw_sfs /* create stack frame */
+ /* if we are maybe leaf,
+ * we have to restore argument and temporary registers
+ */
- /* store all volatile registers and a2, because we will touch it */
+ 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
+ */
- st a2, 96(sp)
- STORE_VOLATILE_INTEGER_REGISTERS(96 + 4)
- STORE_VOLATILE_FLOAT_REGISTERS(96 + 4 + VOLATILE_INTEGER_REGISTERS_SIZE)
+ l itmp3, OUT+(0*4)(sp) /* out[0] contains IntSav */
- /* pass arguments */
+ ahi itmp3, -1
+ jl L_int_done
+ l s4, REGS+(11*4)(sp)
- la a0, apw_sfs(sp) /* pass SP of patcher stub */
- lr a1, pv /* pass PV (if NULL, use findmethod) */
- lhi a2, 0 /* pass RA */
+ ahi itmp3, -1
+ jl L_int_done
+ l s3, REGS+(10*4)(sp)
- /* call patcher_wrapper */
+ ahi itmp3, -1
+ jl L_int_done
+ l s2, REGS+(9*4)(sp)
- bras itmp1, L_apw_bras /* call patcher_wrapper */
- .long patcher_wrapper
-L_apw_bras:
- l itmp1, 0(itmp1)
- basr %r14, itmp1
+ ahi itmp3, -1
+ jl L_int_done
+ l s1, REGS+(8*4)(sp)
- /* store return value */
+ ahi itmp3, -1
+ jl L_int_done
+ l s0, REGS+(7*4)(sp)
- st v0,0(sp) /* save return value */
+L_int_done:
- /* restore volatile registers */
+ /* restore callee saved float registers */
- l a2, 96(sp)
- LOAD_VOLATILE_INTEGER_REGISTERS(96 + 4)
- LOAD_VOLATILE_FLOAT_REGISTERS(96 + 4 + VOLATILE_INTEGER_REGISTERS_SIZE)
+ l itmp3, OUT+(1*4)(sp) /* out[1] contains FltSav */
- l itmp3, 0(sp) /* restore return value */
- ltr itmp3, itmp3 /* exception thrown ? */
- jne L_asm_patcher_wrapper_exception /* handle exception */
- l itmp3, apw_sfs + (5 * 4)(sp) /* load return address to JIT from stack */
- ahi sp, apw_sfs + (6 * 4) /* remove stack frame, and stack frame by patcher stub */
- br itmp3 /* return */
+ ahi itmp3, -1
+ jl L_flt_done
+ ld %f6, FREGS+(6*8)(sp)
-L_asm_patcher_wrapper_exception:
- lr xptr,itmp3 /* get exception */
- l xpc, apw_sfs + (5 * 4)(sp) /* load return address to JIT from stack */
- ahi sp, apw_sfs + (6 * 4) /* remove stack frame, and stack frame by patcher stub */
- j L_asm_handle_exception
+ ahi itmp3, -1
+ jl L_flt_done
+ ld %f4, FREGS+(4*8)(sp)
-#if 0
+L_flt_done:
-/* asm_replacement_out *********************************************************
+L_restore_done:
- This code is jumped to from the replacement-out stubs that are executed
- when a thread reaches an activated replacement point.
+ /* write new values for special registers */
- The purpose of asm_replacement_out is to read out the parts of the
- execution state that cannot be accessed from C code, store this state,
- and then call the C function replace_me.
+ l xptr, REGS+(1*4)(sp)
+ l xpc, REGS+(12*4)(sp)
+ l pv, REGS+(13*4)(sp)
+ l sp, REGS+(15*4)(sp)
- Stack layout:
- 8 start of stack inside method to replace
- 0 rplpoint * info on the replacement point that was reached
+ br xpc /* jump to handler */
-*******************************************************************************/
+# undef STACKFRAMESIZE
+# undef REGS
+# undef FREGS
+# undef OUT
-/* some room to accomodate changes of the stack frame size during replacement */
- /* XXX we should find a cleaner solution here */
-#define REPLACEMENT_ROOM 512
+#if 0
-asm_replacement_out:
- /* create stack frame */
- sub $(sizeexecutionstate + REPLACEMENT_ROOM),sp
-
- /* save registers in execution state */
- mov %rax,(RAX*8+offes_intregs)(sp)
- mov %rbx,(RBX*8+offes_intregs)(sp)
- mov %rcx,(RCX*8+offes_intregs)(sp)
- mov %rdx,(RDX*8+offes_intregs)(sp)
- mov %rsi,(RSI*8+offes_intregs)(sp)
- mov %rdi,(RDI*8+offes_intregs)(sp)
- mov %rbp,(RBP*8+offes_intregs)(sp)
- movq $0 ,(RSP*8+offes_intregs)(sp) /* not used */
- mov %r8 ,(R8 *8+offes_intregs)(sp)
- mov %r9 ,(R9 *8+offes_intregs)(sp)
- mov %r10,(R10*8+offes_intregs)(sp)
- mov %r11,(R11*8+offes_intregs)(sp)
- mov %r12,(R12*8+offes_intregs)(sp)
- mov %r13,(R13*8+offes_intregs)(sp)
- mov %r14,(R14*8+offes_intregs)(sp)
- mov %r15,(R15*8+offes_intregs)(sp)
-
- movq %xmm0 ,(XMM0 *8+offes_fltregs)(sp)
- movq %xmm1 ,(XMM1 *8+offes_fltregs)(sp)
- movq %xmm2 ,(XMM2 *8+offes_fltregs)(sp)
- movq %xmm3 ,(XMM3 *8+offes_fltregs)(sp)
- movq %xmm4 ,(XMM4 *8+offes_fltregs)(sp)
- movq %xmm5 ,(XMM5 *8+offes_fltregs)(sp)
- movq %xmm6 ,(XMM6 *8+offes_fltregs)(sp)
- movq %xmm7 ,(XMM7 *8+offes_fltregs)(sp)
- movq %xmm8 ,(XMM8 *8+offes_fltregs)(sp)
- movq %xmm9 ,(XMM9 *8+offes_fltregs)(sp)
- movq %xmm10,(XMM10*8+offes_fltregs)(sp)
- movq %xmm11,(XMM11*8+offes_fltregs)(sp)
- movq %xmm12,(XMM12*8+offes_fltregs)(sp)
- movq %xmm13,(XMM13*8+offes_fltregs)(sp)
- movq %xmm14,(XMM14*8+offes_fltregs)(sp)
- movq %xmm15,(XMM15*8+offes_fltregs)(sp)
-
- /* calculate sp of method */
- mov sp,itmp1
- add $(sizeexecutionstate + REPLACEMENT_ROOM + 8),itmp1
- mov itmp1,(offes_sp)(sp)
-
- /* pv must be looked up via AVL tree */
- movq $0,(offes_pv)(sp)
-
- /* call replace_me */
- mov -8(itmp1),a0 /* rplpoint * */
- mov sp,a1 /* arg1: execution state */
- call replace_me@PLT /* call C function replace_me */
- call abort@PLT /* NEVER REACHED */
-
-/* asm_replacement_in **********************************************************
-
- This code writes the given execution state and jumps to the replacement
- code.
-
- This function never returns!
-
- C prototype:
- void asm_replacement_in(executionstate *es);
+/* asm_abstractmethoderror *****************************************************
-*******************************************************************************/
+ Creates and throws an AbstractMethodError.
-asm_replacement_in:
- mov a0,%rbp /* executionstate *es */
-
- /* set new sp */
- mov (offes_sp)(%rbp),%rsp
-
- /* store address of new code */
- push (offes_pc)(%rbp)
-
- /* copy registers from execution state */
- movq (XMM0 *8+offes_fltregs)(%rbp),%xmm0
- movq (XMM1 *8+offes_fltregs)(%rbp),%xmm1
- movq (XMM2 *8+offes_fltregs)(%rbp),%xmm2
- movq (XMM3 *8+offes_fltregs)(%rbp),%xmm3
- movq (XMM4 *8+offes_fltregs)(%rbp),%xmm4
- movq (XMM5 *8+offes_fltregs)(%rbp),%xmm5
- movq (XMM6 *8+offes_fltregs)(%rbp),%xmm6
- movq (XMM7 *8+offes_fltregs)(%rbp),%xmm7
- movq (XMM8 *8+offes_fltregs)(%rbp),%xmm8
- movq (XMM9 *8+offes_fltregs)(%rbp),%xmm9
- movq (XMM10*8+offes_fltregs)(%rbp),%xmm10
- movq (XMM11*8+offes_fltregs)(%rbp),%xmm11
- movq (XMM12*8+offes_fltregs)(%rbp),%xmm12
- movq (XMM13*8+offes_fltregs)(%rbp),%xmm13
- movq (XMM14*8+offes_fltregs)(%rbp),%xmm14
- movq (XMM15*8+offes_fltregs)(%rbp),%xmm15
-
- mov (RAX*8+offes_intregs)(%rbp),%rax
- mov (RBX*8+offes_intregs)(%rbp),%rbx
- mov (RCX*8+offes_intregs)(%rbp),%rcx
- mov (RDX*8+offes_intregs)(%rbp),%rdx
- mov (RSI*8+offes_intregs)(%rbp),%rsi
- mov (RDI*8+offes_intregs)(%rbp),%rdi
- mov (R8 *8+offes_intregs)(%rbp),%r8
- mov (R9 *8+offes_intregs)(%rbp),%r9
- mov (R10*8+offes_intregs)(%rbp),%r10
- mov (R11*8+offes_intregs)(%rbp),%r11
- mov (R12*8+offes_intregs)(%rbp),%r12
- mov (R13*8+offes_intregs)(%rbp),%r13
- mov (R14*8+offes_intregs)(%rbp),%r14
- mov (R15*8+offes_intregs)(%rbp),%r15
-
- mov (RBP*8+offes_intregs)(%rbp),%rbp
-
- /* jump to new code */
- ret
-
-
-/* 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_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_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
-
-#endif /* if 0 */
-
-/* TODO use move here ? */
-
-asm_getclassvalues_atomic:
-_crit_restart:
-_crit_begin:
- l %r0,offbaseval(a0)
- l %r1,offdiffval(a0)
- l a3,offbaseval(a1)
-_crit_end:
- st %r0,offcast_super_baseval(a2)
- st %r1,offcast_super_diffval(a2)
- st a3,offcast_sub_baseval(a2)
- br %r14
-
- .data
-
-asm_criticalsections:
-#if defined(ENABLE_THREADS)
- .long _crit_begin
- .long _crit_end
- .long _crit_restart
#endif
- .long 0
-
-/* disable exec-stacks ********************************************************/
-
-#if 0
-
-#if defined(__linux__) && defined(__ELF__)
- .section .note.GNU-stack,"",@progbits
-#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
-#endif /* if 0 */
/*
* These are local overrides for various environment variables in Emacs.