-/* src/vm/jit/x86_64/asmpart.S - Java-C interface functions for x86_64
+/* src/vm/jit/s390/asmpart.S - Java-C interface functions for s390
- Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+ 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
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- Contact: cacao@cacaojvm.org
-
- Authors: Andreas Krall
- Reinhard Grafl
- Christian Thalinger
-
- Changes: Edwin Steiner
-
- $Id: asmpart.S 7283 2007-02-04 19:41:14Z pm $
-
*/
#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_vm_call_method_float
.globl asm_vm_call_method_double
.globl asm_vm_call_method_exception_handler
-
- .globl asm_call_jit_compiler
+ .globl asm_vm_call_method_end
.globl asm_handle_exception
.globl asm_handle_nat_exception
.globl asm_abstractmethoderror
- .globl asm_patcher_wrapper
-
- .globl asm_replacement_out
- .globl asm_replacement_in
-
.globl asm_builtin_f2i
.globl asm_builtin_f2l
.globl asm_builtin_d2i
.globl asm_builtin_d2l
- .globl asm_criticalsections
- .globl asm_getclassvalues_atomic
-
-#if 0
-asm_vm_call_method:
-asm_vm_call_method_int:
-asm_vm_call_method_long:
-asm_vm_call_method_float:
-asm_vm_call_method_double:
-#endif
-asm_vm_call_method_exception_handler:
-#if 0
-asm_call_jit_compiler:
-#endif
-asm_handle_exception:
-asm_handle_nat_exception:
asm_abstractmethoderror:
-asm_patcher_wrapper:
-asm_replacement_out:
-asm_replacement_in:
+ .long 0
asm_builtin_f2i:
+ .long 0
asm_builtin_f2l:
+ .long 0
asm_builtin_d2i:
+ .long 0
asm_builtin_d2l:
-asm_criticalsections:
-asm_getclassvalues_atomic:
.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) *
* void *arg1, void *arg2, void *arg3, void *arg4); *
* *
*******************************************************************************/
- .align 8
-
- .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 0 /* intsave */
- .long 0 /* isleaf */
- .long 0 /* IsSync */
- .long 0 /* frame size */
- .quad 0 /* codeinfo pointer */
+ .long 0 /* fltsave */
+ .long 0 /* intsave */
+ .long 0 /* IsLeaf */
+ .long 0 /* frame size */
+ .long 0 /* codeinfo pointer */
asm_vm_call_method:
asm_vm_call_method_int:
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
- 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 */
- ahi sp, -16 /* allocate stack space for local variables */
- stm a0, a2, 0(sp) /* save arguments */
-
- 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 */
+ ahi sp, -8*4 /* allocate stack frame */
- tm offvmargtype(itmp1), 0x01 /* is this a 2 word type ? */
- jne L_register_handle_long
+ /* a0: PV */
+ /* a1: data structure */
+ /* a2: number of stack arguments */
- ahi s0, 1 /* increment integer arg counter */
- ahi s2, 1 /* increment integer register counter */
+ 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)
- /* handle argument */
+ lr s0, a1 /* data structure */
+ lr %r0, a2 /* number of stack arguments */
- 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 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)
-L_register_handle_long:
+ ld fa0, 5*8(s0)
+ ld fa1, 6*8(s0)
- 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
+ lr s1, sp /* backup stack pointer */
-L_register_handle_long_continue:
+ 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 */
- ahi s0, 1 /* increment integer arg counter */
- ahi s2, 2 /* consume 2 integer arg registers */
+L_asm_vm_call_method_stack_copy_loop:
- /* handle argument */
+ 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
- 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_asm_vm_call_method_stack_copy_done:
-L_register_handle_float:
+ la mptr, 2*4(s1) /* load method pointer */
+ l pv, 0(mptr) /* load procedure vector from method pointer */
+ basr ra, pv /* call method */
- 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 */
-
- je L_copy_done /* no arguments left for stack */
-
- sll s4, 3 /* allocate 8 bytes per parameter on stack */
- lr s3, sp /* backup stack pointer */
- 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_asm_vm_call_method_return:
-L_stack_copy_loop:
+ lr sp, s1 /* restore stack pointer */
+ 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 itmp1, sizevmarg /* forward argument block pointer */
- ahi itmp2, -1 /* decrement argument counter */
- je L_copy_done /* all arguments done */
+ ahi sp, 8*4 /* remove stackframe */
+ br ra /* return */
- tm offvmargtype(itmp1), 0x0 /* is this a float/double type? */
- jne L_stack_handle_float
-L_stack_handle_int:
+asm_vm_call_method_exception_handler:
+ lr a0, xptr
- ahi s0, -1 /* decrement number of integer arguments in regs */
- jhe L_stack_copy_loop /* argument is in register */
+ ahi sp, -96
+ CALL_PIC(builtin_throw_exception, avcmeh)
+ ahi sp, 96
- tm offvmargtype(itmp1), 0x01 /* is this a 2 word type ? */
- jne L_stack_handle_long
+ j L_asm_vm_call_method_return
- mvc 0(4, s2), offvmargdata(itmp1) /* copy integer value */
- ahi s2, 4
- j L_stack_copy_loop
+asm_vm_call_method_end:
+ brc 0,0
-L_stack_handle_long:
+/* 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. *
+* *
+*******************************************************************************/
- mvc 0(8, s2), offvmargdata(itmp1) /* copy long value */
- ahi s2, 8
- j L_stack_copy_loop
+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)
-L_stack_handle_float:
+ /* call md_handle_exception */
- ahi s1, -1 /* decrement number of float arguments in regs */
- jhe L_stack_copy_loop /* argument is in register */
+ la a0, REGS(sp)
+ la a1, FREGS(sp)
+ la a2, OUT(sp)
- tm offvmargtype(itmp1), 0x01 /* is this a 2 word type ? */
- jne L_stack_handle_double
+ CALL_PIC(md_handle_exception, ahe)
- mvc 0(4, s2), offvmargdata(itmp1) /* copy float value */
- ahi s2, 4
- j L_stack_copy_loop
+ /* restore %r12 */
-L_stack_handle_double:
+ l %r12, REGS+(12*4)(sp)
- mvc 0(8, s2), offvmargdata(itmp1) /* copy double value */
- ahi s2, 8
- j L_stack_copy_loop
+ l itmp3, OUT+(2*4)(sp) /* out[2] contains maybe leaf flag */
+ ltr itmp3, itmp3
+ je L_restore_saved
-L_copy_done:
+L_restore_temporary_and_argument:
- /* 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.
+ /* if we are maybe leaf,
+ * we have to restore argument and temporary registers
*/
- /* load address of L_asm_call_jit_compiler into memory */
-
- basr mptr, 0 /* store PC */
-L_basr:
- la mptr, L_asm_call_jit_compiler-L_basr(mptr) /* add offset to PC */
- st mptr, 12(s3) /* store on stack */
-
- l itmp1, 0(s3) /* load methodinfo for compiler */
- la mptr, 12(s3) /* store **function in mptr for compiler */
-
- /* call L_asm_call_jit_compiler like JIT code would do */
-
- l itmp3, 0(mptr) /* load address of target from memory */
- basr %r14, itmp3 /* jump to target */
-
- /* todo will s4 survive the call? */
- ar sp, s4 /* remove stack space for arguments */
-
-L_asm_vm_call_method_return:
-
- ahi sp, 16 /* remove stack space for local variables */
- lm %r6, %r15, 24(sp) /* restore callers registers */
- br %r14 /* return */
-
-/* .... */
-
-L_no_args:
- lr s3, sp
- j L_copy_done
-
-L_handle_i0:
- l a0, offvmargdata(itmp1)
- j L_register_copy
-L_handle_i1:
- l a1, offvmargdata(itmp1)
- j L_register_copy
-L_handle_i2:
- l a2, offvmargdata(itmp1)
- j L_register_copy
-L_handle_i3:
- l a3, offvmargdata(itmp1)
- j L_register_copy
-L_handle_i4:
- l a4, offvmargdata(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
-
-
-/****************** function asm_call_jit_compiler *****************************
-* *
-* invokes the compiler for untranslated JavaVM methods. *
-* *
-* itmp1: methodinfo pointer *
-* itmp2: 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
-*/
+ 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
+ */
-/* This is called from a compiler stub.
- * Arguments are already in registers and the stack is setup like in CACAO.
- */
+ l itmp3, OUT+(0*4)(sp) /* out[0] contains IntSav */
-asm_call_jit_compiler:
-L_asm_call_jit_compiler:
+ ahi itmp3, -1
+ jl L_int_done
+ l s5, REGS+(12*4)(sp)
-# define ACJC_STACKFRAME (4 + (4 * 4) + (2 * 8) + 96)
+ ahi itmp3, -1
+ jl L_int_done
+ l s4, REGS+(11*4)(sp)
- ahi sp,-ACJC_STACKFRAME /* allocate stack space */
+ ahi itmp3, -1
+ jl L_int_done
+ l s3, REGS+(10*4)(sp)
- 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 %r14,96+32(sp) /* store return address */
+ ahi itmp3, -1
+ jl L_int_done
+ l s2, REGS+(9*4)(sp)
- /* load arguments */
+ ahi itmp3, -1
+ jl L_int_done
+ l s1, REGS+(8*4)(sp)
- lr a0,itmp1 /* pass methodinfo pointer */
- lr a1,itmp2 /* pass method pointer */
- la a2,ACJC_STACKFRAME(sp) /* pass java sp */
- la a3,0(%r14) /* pass return address, make sure bit 32 is 0 */
+ ahi itmp3, -1
+ jl L_int_done
+ l s0, REGS+(7*4)(sp)
- /* call jit_asm_compile in a PIC way */
+L_int_done:
- bras itmp3, L_bras_jac
- .long jit_asm_compile
-L_bras_jac:
- l itmp3, 0(itmp3)
- basr %r14, itmp3
+ /* restore callee saved float registers */
- lr pv, v0 /* save return value */
+ /* there are currently none */
- 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 */
- ld %r14,96+32(sp) /* restore return address */
+L_flt_done:
-#if 0
- ltr v0,v0
- je L_asm_call_jit_compiler_exception
-#endif
+L_restore_done:
- br pv /* call the method, it will return to the caller */
+ /* 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)
-L_asm_call_jit_compiler_exception:
-#if 0
- call exceptions_get_and_clear_exception@PLT
- pop xpc /* delete return address */
- sub $3,xpc /* faulting address is ra - 3 */
- jmp L_asm_handle_exception
-#endif
- .long 0
+ br xpc /* jump to handler */
+# undef STACKFRAMESIZE
+# undef REGS
+# undef FREGS
+# undef OUT
#if 0
-/* 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 *****************************************************
sub $3,xpc /* exception address is ra - 3 */
jmp L_asm_handle_exception
-
-/* asm_patcher_wrapper *********************************************************
-
- XXX
-
- Stack layout:
- 40 return address
- 32 pointer to virtual java_objectheader
- 24 machine code (which is patched back later)
- 16 unresolved class/method/field reference
- 8 data segment displacement from load instructions
- 0 pointer to patcher function
- -8 bp
-
-*******************************************************************************/
-
-asm_patcher_wrapper:
- push bp /* save base pointer */
- mov sp,bp /* move actual sp to bp */
- sub $((3+ARG_CNT+TMP_CNT)*8+sizestackframeinfo),sp
- and $0xfffffffffffffff0,sp /* align sp to 16-byte (this is for */
- /* leaf functions) */
-
- SAVE_ARGUMENT_REGISTERS(3)
- SAVE_TEMPORARY_REGISTERS(3+ARG_CNT)
-
- mov itmp1,0*8(sp) /* save itmp1 and itmp2 */
- mov itmp2,1*8(sp) /* can be used by some instructions */
-
- mov bp,a0 /* pass SP of patcher stub */
- add $(1*8),a0
- mov $0,a1 /* pass PV (if NULL, use findmethod) */
- mov $0,a2 /* pass RA (it's on the stack) */
- call patcher_wrapper@PLT
- mov v0,2*8(sp) /* save return value */
-
- RESTORE_ARGUMENT_REGISTERS(3)
- RESTORE_TEMPORARY_REGISTERS(3+ARG_CNT)
-
- mov 0*8(sp),itmp1 /* restore itmp1 and itmp2 */
- mov 1*8(sp),itmp2 /* can be used by some instructions */
- mov 2*8(sp),itmp3 /* restore return value */
-
- mov bp,sp /* restore original sp */
- pop bp /* restore bp */
- add $(5*8),sp /* remove patcher stackframe, keep RA */
-
- test itmp3,itmp3 /* exception thrown? */
- jne L_asm_patcher_wrapper_exception
- ret /* call new patched code */
-
-L_asm_patcher_wrapper_exception:
- mov itmp3,xptr /* get exception */
- pop xpc /* get and remove return address */
- jmp L_asm_handle_exception
-
-
-/* asm_replacement_out *********************************************************
-
- This code is jumped to from the replacement-out stubs that are executed
- when a thread reaches an activated replacement point.
-
- 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.
-
- Stack layout:
- 8 start of stack inside method to replace
- 0 rplpoint * info on the replacement point that was reached
-
-*******************************************************************************/
-
-/* some room to accomodate changes of the stack frame size during replacement */
- /* XXX we should find a cleaner solution here */
-#define REPLACEMENT_ROOM 512
-
-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_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_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_getclassvalues_atomic:
-_crit_restart:
-_crit_begin:
- movl offbaseval(a0),itmp1l
- movl offdiffval(a0),itmp2l
- movl offbaseval(a1),itmp3l
-_crit_end:
- movl itmp1l,offcast_super_baseval(a2)
- movl itmp2l,offcast_super_diffval(a2)
- movl itmp3l,offcast_sub_baseval(a2)
- ret
-
- .data
-
-asm_criticalsections:
-#if defined(ENABLE_THREADS)
- .quad _crit_begin
- .quad _crit_end
- .quad _crit_restart
#endif
- .quad 0
-
-/* Disable exec-stacks, required for Gentoo ***********************************/
-
-#if defined(__GCC__) && 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.