Christian Thalinger
Changes: Joseph Wenninger
+ Edwin Steiner
- $Id: asmpart.S 4440 2006-02-05 12:03:43Z twisti $
+ $Id: asmpart.S 4643 2006-03-16 18:38:42Z edwin $
*/
#include "vm/jit/i386/md-abi.h"
#include "vm/jit/i386/md-asm.h"
#include "vm/jit/i386/offsets.h"
+#include "vm/jit/i386/arch.h"
#include "vm/jit/methodheader.h"
.globl asm_md_init
- .globl asm_calljavafunction
- .globl asm_calljavafunction_int
-
- .globl asm_calljavafunction2
- .globl asm_calljavafunction2int
- .globl asm_calljavafunction2long
- .globl asm_calljavafunction2float
- .globl asm_calljavafunction2double
+ .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_call_jit_compiler
.globl asm_handle_nat_exception
.globl asm_wrapper_patcher
+ .globl asm_replacement_out
+ .globl asm_replacement_in
+
.globl asm_builtin_f2i
.globl asm_builtin_f2l
.globl asm_builtin_d2i
* method into machine code. *
* *
* C-prototype: *
-* javaobject_header *asm_calljavamethod (methodinfo *m, *
-* void *arg1, void *arg2, void *arg3, void *arg4); *
-* *
-*******************************************************************************/
-
- .align 8
-
- .long 0 /* catch type all */
- .long calljava_xhandler /* handler pc */
- .long calljava_xhandler /* end pc */
- .long asm_calljavafunction /* 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 /* method pointer (pointer to name) */
-
-asm_calljavafunction:
-asm_calljavafunction_int:
- push bp /* allocate stack space */
- mov sp,bp
-
- push %ebx /* save registers */
- push %esi
- push %edi
-
- sub $(4*4),sp /* 4 adress parameters * 4 Bytes */
- mov 5*4(bp),itmp1 /* copy adress parameters to new block*/
- mov itmp1,3*4(sp)
-
- mov 5*4(bp),itmp1
- mov itmp1,2*4(sp)
-
- mov 4*4(bp),itmp1
- mov itmp1,1*4(sp)
-
- mov 3*4(bp),itmp1
- mov itmp1,0*4(sp)
-
- mov 2*4(bp),itmp1 /* move function pointer to %eax */
-
- lea asm_call_jit_compiler,itmp3
- call *itmp3 /* call JIT compiler */
-
-L_asm_calljavafunction_return:
- add $(4*4),sp
- pop %edi /* restore registers */
- pop %esi
- pop %ebx
- leave
- ret
-
-calljava_xhandler:
- push xptr /* pass exception pointer */
- call builtin_throw_exception
- add $4,sp
- xor v0,v0 /* return NULL */
- jmp L_asm_calljavafunction_return
-
-
-/********************* 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_calljavafunction2(methodinfo *m, *
+* javaobject_header *asm_vm_call_method(methodinfo *m, *
* u4 count, u4 size, void *callblock); *
* *
*******************************************************************************/
.long 0 /* catch type all */
.long calljava_xhandler2 /* handler pc */
.long calljava_xhandler2 /* end pc */
- .long asm_calljavafunction2 /* start pc */
+ .long L_asm_vm_call_method /* start pc */
.long 1 /* extable size */
.long 0 /* line number table start */
.long 0 /* line number table size */
.long 0 /* frame size */
.long 0 /* method pointer (pointer to name) */
-asm_calljavafunction2:
-asm_calljavafunction2int:
-asm_calljavafunction2long:
-asm_calljavafunction2float:
-asm_calljavafunction2double:
+asm_vm_call_method:
+asm_vm_call_method_int:
+asm_vm_call_method_long:
+asm_vm_call_method_float:
+asm_vm_call_method_double:
+L_asm_vm_call_method: /* required for PIC code */
push %ebp
- mov %esp,%ebp /* save stackptr */
+ mov %esp,%ebp /* save stackptr */
- push %ebx /* save registers */
+ push %ebx /* save registers */
push %esi
push %edi
- mov 20(%ebp),%eax /* pointer to arg block (4(push)+4(return)+4+4+4)*/
- mov 12(%ebp),%ecx /* arg count (4(push)+4(return)+4 */
+ mov 4*4(%ebp),%eax /* pointer to arg block (4(push)+4(return)+4+4)*/
+ mov 3*4(%ebp),%ecx /* arg count (4(push)+4(return)+4 */
xor %esi,%esi /* clear stackframe size (MUST be */
/* before args check, may be zero!!!) */
mov %eax,%edi /* save pointer to arg block */
calljava_calcstacksize:
- mov offjniitemtype(%eax),%ebx
+ mov offvmargtype(%eax),%ebx
test $1,%ebx /* two word type? */
jz calljava_onewordtype
add $4,%esi /* add 1 slot to stackframe size */
sub $1,%edx
test %edx,%edx /* any args left? */
jz calljava_setstack
- add $sizejniblock,%eax /* goto next argument block */
+ add $sizevmarg,%eax /* goto next argument block */
jmp calljava_calcstacksize
calljava_setstack:
mov %esp,%edi /* move stackpointer into temp variable */
calljava_copyloop:
- mov offjniitem(%eax),%edx /* copy 4 Byte of Argument */
+ mov offvmargdata(%eax),%edx /* copy 4 Byte of Argument */
mov %edx,(%edi)
- add $4,%edi /* increase sp to next argument */
- mov offjniitemtype(%eax),%ebx /* type -> ebx */
- test $1,%ebx /* Two Word Type? */
+ add $4,%edi /* increase sp to next argument */
+ mov offvmargtype(%eax),%ebx /* type -> ebx */
+ test $1,%ebx /* two word type? */
jz calljava_copynext
- mov offjniitem+4(%eax),%edx /* copy upper 4 Byte of 2 Word Type */
+ mov offvmargdata+4(%eax),%edx /* copy upper 4 byte of 2 word type */
mov %edx,(%edi)
- add $4,%edi /* increase sp to next argument */
+ add $4,%edi /* increase sp to next argument */
calljava_copynext:
- sub $1,%ecx /* are there any args left? */
+ sub $1,%ecx /* are there any args left? */
test %ecx,%ecx
jle calljava_copydone
- add $sizejniblock,%eax /* goto next argument block */
+ add $sizevmarg,%eax /* goto next argument block */
jmp calljava_copyloop
calljava_copydone:
- mov 8(%ebp),%eax /* move function pointer to %eax */
+ mov 2*4(%ebp),itmp1 /* move function pointer to itmp1 */
- lea asm_call_jit_compiler,itmp3
+ lea L_asm_call_jit_compiler,itmp3
call *itmp3 /* call JIT compiler */
-L_asm_calljavafunction2_return:
+L_asm_vm_call_method_return:
add %esi,%esp /* remove arg stack frame */
pop %edi /* restore registers */
pop %esi
call builtin_throw_exception
add $4,sp
xor v0,v0 /* return NULL */
- jmp L_asm_calljavafunction2_return
+ jmp L_asm_vm_call_method_return
-/****************** function asm_call_jit_compiler *****************************
-* *
-* invokes the compiler for untranslated JavaVM methods. *
-* *
-* Register R0 contains a pointer to the method info structure (prepared *
-* by createcompilerstub). Using the return address in R26 and the *
-* offset in the LDA instruction or using the value in methodptr R28 the *
-* patching address for storing the method address can be computed: *
-* *
-* method address was either loaded using *
-* *
-* i386_mov_imm_reg(a, REG_ITMP2) ; invokestatic/special *
-* i386_call_reg(REG_ITMP2) *
-* *
-* or *
-* *
-* i386_mov_membase_reg(REG_SP, 0, REG_ITMP1) ; invokevirtual/interface *
-* i386_mov_membase_reg(REG_ITMP1, OFFSET(, vftbl), REG_ITMP2) *
-* i386_mov_membase_reg(REG_ITMP2, OFFSET(vftbl, table[0]) + \ *
-* sizeof(methodptr) * m->vftblindex, REG_ITMP1) *
-* i386_call_reg(REG_ITMP1) *
-* *
-* in the static case the method pointer can be computed using the *
-* return address and the lda function following the jmp instruction *
-* *
+/* asm_call_jit_compiler *******************************************************
+
+ Invokes the compiler for untranslated JavaVM methods.
+
+ Register R0 contains a pointer to the method info structure (prepared
+ by createcompilerstub). Using the return address in R26 and the
+ offset in the LDA instruction or using the value in methodptr R28 the
+ patching address for storing the method address can be computed:
+
+ Method address was either loaded using
+
+ i386_mov_imm_reg(a, REG_ITMP2) ; invokestatic/special
+ i386_call_reg(REG_ITMP2)
+
+ or
+
+ i386_mov_membase_reg(REG_SP, 0, REG_ITMP1) ; invokevirtual/interface
+ i386_mov_membase_reg(REG_ITMP1, OFFSET(, vftbl), REG_ITMP2)
+ i386_mov_membase_reg(REG_ITMP2, OFFSET(vftbl, table[0]) + \
+ sizeof(methodptr) * m->vftblindex, REG_ITMP1)
+ i386_call_reg(REG_ITMP1)
+
+ In the static case the method pointer can be computed using the
+ return address and the lda function following the jmp instruction.
+
*******************************************************************************/
asm_call_jit_compiler:
+L_asm_call_jit_compiler: /* required for PIC code */
sub $((4+2)*4+sizestackframeinfo),sp /* create stack frame */
mov itmp1,(4+0)*4(sp) /* save method pointer */
pop xpc /* get return address */
sub $2,xpc /* faulting address is ra - 2 */
- jmp asm_handle_exception
+ jmp L_asm_handle_exception
/* asm_handle_exception ********************************************************
add $4,sp /* clear return address of native stub*/
asm_handle_exception:
+L_asm_handle_exception: /* required for PIC code */
sub $((ARG_CNT+TMP_CNT)*4),sp /* create maybe-leaf stackframe */
SAVE_ARGUMENT_REGISTERS(0) /* we save arg and temp registers in */
XXX
Stack layout:
- 20 return address
+ 24 return address
+ 20 REG_ITMP3
16 pointer to virtual java_objectheader
12 last byte of machine code (xmcode)
8 machine code (which is patched back later)
mov itmp1,0*4(sp) /* stackframeinfo pointer */
movl $0,1*4(sp) /* if pv is NULL, use findmethod */
mov sp,itmp2
- add $((6+2+4)*4+sizestackframeinfo),itmp2
- mov itmp2,2*4(sp)
- mov ((5+2+4)*4+sizestackframeinfo)(sp),itmp3
- mov itmp3,3*4(sp)
+ add $((7+2+4)*4+sizestackframeinfo),itmp2
+ mov itmp2,2*4(sp) /* pass Java sp */
+ mov ((6+2+4)*4+sizestackframeinfo)(sp),itmp3
+ mov itmp3,3*4(sp) /* pass ra to java function */
call stacktrace_create_inline_stackframeinfo
mov sp,itmp1 /* pass stack pointer */
mov itmp1,0*4(sp) /* stackframeinfo pointer */
call stacktrace_remove_stackframeinfo
- mov (0+4)*4(sp),itmp1 /* restore itmp1 and itmp2 */
- mov (1+4)*4(sp),itmp2 /* may be used by some instructions */
mov 1*4(sp),itmp3 /* restore return value */
-
- add $((5+2+4)*4+sizestackframeinfo),sp /* remove stack frame, keep ra */
test itmp3,itmp3 /* exception thrown? */
jz L_asm_wrapper_patcher_exception
+
+ mov (0+4)*4(sp),itmp1 /* restore itmp1 and itmp2 */
+ mov (1+4)*4(sp),itmp2 /* may be used by some instructions */
+ mov ((5+2+4)*4+sizestackframeinfo)(sp),itmp3
+ add $((6+2+4)*4+sizestackframeinfo),sp /* remove stack frame, keep ra */
+
ret /* call new patched code */
L_asm_wrapper_patcher_exception:
+ add $((6+2+4)*4+sizestackframeinfo),sp /* remove stack frame, keep ra */
+
#if defined(USE_THREADS) && defined(NATIVE_THREADS)
call builtin_asm_get_exceptionptrptr
mov v0,itmp2
movl $0,(itmp2) /* clear the exception pointer */
pop xpc /* get and remove return address */
- jmp asm_handle_exception
+ 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:
+ 4 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 %eax,(EAX*8+offes_intregs)(sp)
+ mov %ebx,(EBX*8+offes_intregs)(sp)
+ mov %ecx,(ECX*8+offes_intregs)(sp)
+ mov %edx,(EDX*8+offes_intregs)(sp)
+ mov %esi,(ESI*8+offes_intregs)(sp)
+ mov %edi,(EDI*8+offes_intregs)(sp)
+ mov %ebp,(EBP*8+offes_intregs)(sp)
+ movl $0 ,(ESP*8+offes_intregs)(sp) /* not used */
+
+#ifndef NDEBUG
+ /* clear high 32bit */
+ movl $0,(4+0*8+offes_intregs)(sp)
+ movl $0,(4+1*8+offes_intregs)(sp)
+ movl $0,(4+2*8+offes_intregs)(sp)
+ movl $0,(4+3*8+offes_intregs)(sp)
+ movl $0,(4+4*8+offes_intregs)(sp)
+ movl $0,(4+5*8+offes_intregs)(sp)
+ movl $0,(4+6*8+offes_intregs)(sp)
+ movl $0,(4+7*8+offes_intregs)(sp)
+#endif
+
+ /* calculate sp of method */
+ mov sp,itmp1
+ add $(sizeexecutionstate + REPLACEMENT_ROOM + 4),itmp1
+ mov itmp1,(offes_sp)(sp)
+
+ /* pv must be looked up via AVL tree */
+ movl $0,(offes_pv)(sp)
+ /* call replace_me */
+ mov -4(itmp1),itmp1 /* rplpoint * */
+ push sp /* arg1: execution state */
+ push itmp1 /* arg0: replacement point */
+ call replace_me /* call C function replace_me */
+ call abort /* 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 4(sp),%ebp /* executionstate *es */
+
+ /* set new sp */
+ mov (offes_sp)(%ebp),%esp
+
+ /* store address of new code */
+ push (offes_pc)(%ebp)
+
+ /* copy registers from execution state */
+ mov (EAX*8+offes_intregs)(%ebp),%eax
+ mov (EBX*8+offes_intregs)(%ebp),%ebx
+ mov (ECX*8+offes_intregs)(%ebp),%ecx
+ mov (EDX*8+offes_intregs)(%ebp),%edx
+ mov (ESI*8+offes_intregs)(%ebp),%esi
+ mov (EDI*8+offes_intregs)(%ebp),%edi
+
+ mov (EBP*8+offes_intregs)(%ebp),%ebp
+
+ /* jump to new code */
+ ret
/************************ function asm_builtin_x2x *****************************
* *
* c-basic-offset: 4
* tab-width: 4
* End:
+ * vim:noexpandtab:sw=4:ts=4:
*/