-/* -*- mode: asm; tab-width: 4 -*- */
-/****************************** asmpart.c **************************************
-* *
-* It contains the Java-C interface functions for i386 processors. *
-* *
-* Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst *
-* *
-* See file COPYRIGHT for information on usage and disclaimer of warranties *
-* *
-* Authors: Andreas Krall EMAIL: cacao@complang.tuwien.ac.at *
-* Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at *
-* Christian Thalinger *
-* *
-* Last Change: $Id: asmpart.S 742 2003-12-13 20:25:05Z stefan $ *
-* *
-*******************************************************************************/
+/* src/vm/jit/i386/asmpart.S - Java-C interface functions for i386
-#include "offsets.h"
+ 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
- .text
+ 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.
-/********************* exported functions and variables ***********************/
+ 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.
- .globl has_no_x_instr_set
- .globl asm_calljavamethod
- .globl asm_calljavafunction
- .globl asm_calljavafunction2
- .globl asm_calljavafunction2long
- .globl asm_calljavafunction2double
+ 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.
- .globl asm_call_jit_compiler
- .globl asm_dumpregistersandcall
- .globl asm_handle_builtin_exception
- .globl asm_handle_nat_exception
- .globl asm_handle_exception
- .globl asm_builtin_checkcast
- .globl asm_builtin_checkarraycast
- .globl asm_builtin_newarray
- .globl asm_builtin_anewarray
- .globl asm_builtin_newarray_array
- .globl asm_builtin_aastore
- .globl asm_builtin_monitorenter
- .globl asm_builtin_monitorexit
- .globl asm_builtin_ldiv
- .globl asm_builtin_lrem
- .globl asm_builtin_f2i
- .globl asm_builtin_f2l
- .globl asm_builtin_d2i
- .globl asm_builtin_d2l
- .globl asm_builtin_arrayinstanceof
- .globl asm_perform_threadswitch
- .globl asm_initialize_thread_stack
- .globl asm_switchstackandcall
- .globl asm_getcallingmethod
- .globl asm_builtin_trace
- .globl asm_builtin_exittrace
- .globl asm_xadd
-
-/*************************** imported functions *******************************/
-
- .globl jit_compile
- .globl builtin_monitorexit
- .globl builtin_throw_exception
- .globl builtin_trace_exception
- .globl class_java_lang_Object
- .globl findmethod
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
- .globl cast_lock
- .globl cast_unlock
-#endif
+*/
-/*********************** function has_no_x_instr_set ***************************
-* *
-* determines if the byte support instruction set (21164a and higher) *
-* is available. *
-* *
-* Use it on i386 architecture to init the fpu. *
-* *
-*******************************************************************************/
-has_no_x_instr_set:
- finit /* intitialize the fpu */
+#include "config.h"
- pushl $0x027f /* Round to nearest, 53-bit mode, exceptions masked */
- fldcw (%esp)
- addl $4,%esp
-
- xor %eax,%eax /* result code 0 (not used for i386) */
- ret
+#include "md-asm.h"
+#include "vm/jit/i386/arch.h"
+#include "vm/jit/i386/md-abi.h"
-/********************* function asm_calljavamethod *****************************
-* *
-* This function calls a Java-method (which possibly needs compilation) *
-* with up to 4 parameters. *
-* *
-* This functions calls the JIT-compiler which eventually translates the *
-* method into machine code. *
-* *
-* An possibly throwed exception will be returned to the caller as function *
-* return value, so the java method cannot return a fucntion value (this *
-* function usually calls 'main' and '<clinit>' which do not return a *
-* function value). *
-* *
-* C-prototype: *
-* javaobject_header *asm_calljavamethod (methodinfo *m, *
-* void *arg1, void *arg2, void *arg3, void *arg4); *
-* *
-*******************************************************************************/
+#include "vm/jit/abi-asm.h"
+#include "vm/jit/methodheader.h"
-#define MethodPointer -4
-#define FrameSize -8
-#define IsSync -12
-#define IsLeaf -16
-#define IntSave -20
-#define FltSave -24
-#define ExTableSize -28
-#define ExTableStart -28
-
-#define ExEntrySize -16
-#define ExStartPC -4
-#define ExEndPC -8
-#define ExHandlerPC -12
-#define ExCatchType -16
-
-call_name:
- .ascii "calljavamethod\0\0"
-
-/* .align 3 */
- .align 8
- .long 0 /* catch type all */
- .long calljava_xhandler /* handler pc */
- .long calljava_xhandler /* end pc */
- .long asm_calljavamethod /* start pc */
- .long 1 /* extable size */
- .long 0 /* fltsave */
- .long 0 /* intsave */
- .long 0 /* isleaf */
- .long 0 /* IsSync */
- .long 32 /* frame size */
- .long 0 /* method pointer (pointer to name) */
-
-asm_calljavamethod:
- pushl %ebp /* allocate stack space */
- movl %esp, %ebp
-
- push %ebx /* save registers */
- push %esi
- push %edi
-
- subl $32,%esp /* pass the remaining parameters */
- xorl %edx,%edx
-
- movl %edx,28(%esp) /* convert parms to 8 byte */
- movl 24(%ebp),%eax
- movl %eax,24(%esp)
-
- movl %edx,20(%esp)
- movl 20(%ebp),%eax
- movl %eax,16(%esp)
- movl %edx,12(%esp)
- movl 16(%ebp),%eax
- movl %eax,8(%esp)
+ .text
- movl %edx,4(%esp)
- movl 12(%ebp),%eax
- movl %eax,(%esp)
- movl 8(%ebp),%eax /* move function pointer to %eax */
+/* export functions ***********************************************************/
- lea asm_call_jit_compiler,%ecx
- call *%ecx /* call JIT compiler */
-
-calljava_jit:
-calljava_return:
-calljava_ret:
- add $32,%esp
- pop %edi /* restore registers */
- pop %esi
- pop %ebx
-
- xorl %eax,%eax
- leave /* free stack space */
- ret
-
-calljava_xhandler:
- pushl %eax /* pass exception pointer */
- call builtin_throw_exception
- addl $4,%esp
-
- addl $32,%esp
- pop %edi
- pop %esi
- pop %ebx
-
- leave
- ret
+ .globl asm_md_init
+ .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
-/********************* 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); *
-* *
-*******************************************************************************/
+ .globl asm_call_jit_compiler
+ .globl asm_handle_nat_exception
+ .globl asm_handle_exception
-call_name2:
- .ascii "calljavafunction\0\0"
+ .globl asm_abstractmethoderror
-/* .align 3 */
- .align 8
- .long 0 /* catch type all */
- .long calljava_xhandler2 /* handler pc */
- .long calljava_xhandler2 /* end pc */
- .long asm_calljavafunction /* start pc */
- .long 1 /* extable size */
- .long 0 /* fltsave */
- .long 0 /* intsave */
- .long 0 /* isleaf */
- .long 0 /* IsSync */
- .long 32 /* frame size */
- .long 0 /* method pointer (pointer to name) */
-
-asm_calljavafunction:
- pushl %ebp /* allocate stack space */
- movl %esp, %ebp
-
- push %ebx /* save registers */
- push %esi
- push %edi
-
- subl $32,%esp /* pass the remaining parameters */
- xorl %edx,%edx
-
- movl %edx,28(%esp) /* convert parms to 8 byte */
- movl 24(%ebp),%eax
- movl %eax,24(%esp)
-
- movl %edx,20(%esp)
- movl 20(%ebp),%eax
- movl %eax,16(%esp)
-
- movl %edx,12(%esp)
- movl 16(%ebp),%eax
- movl %eax,8(%esp)
-
- movl %edx,4(%esp)
- movl 12(%ebp),%eax
- movl %eax,(%esp)
-
- movl 8(%ebp),%eax /* move function pointer to %eax */
-
- lea asm_call_jit_compiler,%ecx
- call *%ecx /* call JIT compiler */
-
-calljava_jit2:
-calljava_return2:
-calljava_ret2:
- add $32,%esp
- pop %edi /* restore registers */
- pop %esi
- pop %ebx
- leave
- ret
-
-calljava_xhandler2:
- pushl %eax /* pass exception pointer */
- call builtin_throw_exception
- addl $4,%esp
-
- addl $32,%esp
- pop %edi /* restore registers */
- pop %esi
- pop %ebx
- leave
- ret
-
+ .globl asm_patcher_wrapper
+#if defined(ENABLE_REPLACEMENT)
+ .globl asm_replacement_out
+ .globl asm_replacement_in
+#endif
-/********************* 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); *
-* *
-*******************************************************************************/
+ .globl asm_builtin_f2i
+ .globl asm_builtin_f2l
+ .globl asm_builtin_d2i
+ .globl asm_builtin_d2l
-call_name3:
- .ascii "calljavafunction2\0\0"
+ .globl asm_compare_and_swap
+ .globl asm_memory_barrier
-/* .align 3 */
- .align 8
- .long 0 /* catch type all */
- .long calljava_xhandler3 /* handler pc */
- .long calljava_xhandler3 /* end pc */
- .long asm_calljavafunction2 /* start pc */
- .long 1 /* extable size */
- .long 0 /* fltsave */
- .long 0 /* intsave */
- .long 0 /* isleaf */
- .long 0 /* IsSync */
- .long 32 /* frame size */
- .long 0 /* method pointer (pointer to name) */
+ .globl asm_get_cycle_count
+
+
+/* asm_md_init *****************************************************************
+
+ Initialize machine dependent stuff.
+
+ See: http://www.srware.com/linux_numerics.txt
+
+ This puts the X86 FPU in 64-bit precision mode. The default under
+ Linux is to use 80-bit mode, which produces subtle differences from
+ FreeBSD and other systems, eg, (int)(1000*atof("0.3")) is 300 in
+ 64-bit mode, 299 in 80-bit mode.
+
+ Fixes: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=350729
-/********************* 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); *
-* *
*******************************************************************************/
-call_name4:
- .ascii "calljavafunction2double\0\0"
+asm_md_init:
+ sub $4,sp /* allocate space for the FPU state */
+ fnstcw (sp) /* get the FPU state */
+ mov (sp),%eax
+ and $0xfcff,%ax /* remove the extended mode flag */
+ or $0x0200,%ax /* put the double mode flag */
+ mov %eax,(sp) /* store new FPU state */
+ fldcw (sp) /* setup new FPU state */
+ add $4,sp
+ ret
-/* .align 3 */
- .align 8
- .long 0 /* catch type all */
- .long calljava_xhandler3 /* handler pc */
- .long calljava_xhandler3 /* end pc */
- .long asm_calljavafunction2double /* start pc */
- .long 1 /* extable size */
- .long 0 /* fltsave */
- .long 0 /* intsave */
- .long 0 /* isleaf */
- .long 0 /* IsSync */
- .long 32 /* frame size */
- .long 0 /* method pointer (pointer to name) */
/********************* function asm_calljavafunction ***************************
* *
* method into machine code. *
* *
* C-prototype: *
-* javaobject_header *asm_calljavamethod (methodinfo *m, *
-* void *arg1, void *arg2, void *arg3, void *arg4); *
+* javaobject_header *asm_vm_call_method(methodinfo *m, *
+* u4 count, u4 size, void *callblock); *
* *
*******************************************************************************/
-call_name5:
- .ascii "calljavafunction2long\0\0"
-
-/* .align 3 */
.align 8
- .long 0 /* catch type all */
- .long calljava_xhandler3 /* handler pc */
- .long calljava_xhandler3 /* end pc */
- .long asm_calljavafunction2long /* start pc */
- .long 1 /* extable size */
- .long 0 /* fltsave */
- .long 0 /* intsave */
- .long 0 /* isleaf */
- .long 0 /* IsSync */
- .long 32 /* frame size */
- .long 0 /* method pointer (pointer to name) */
-
-
-asm_calljavafunction2:
-asm_calljavafunction2double:
-asm_calljavafunction2long:
- pushl %ebp /* save ebp */
-
-
- movl %esp,%eax /*save stackptr*/
- movl 20(%esp),%ebp
- subl $32,%esp
- movl sizejniblock*3+offjniitem+4(%ebp),%ebx
- movl %ebx,28(%esp)
- movl sizejniblock*3+offjniitem(%ebp),%ebx
- movl %ebx,24(%esp)
+ .long 0 /* catch type all */
+ .long 0 /* 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:
+ push bp
+ mov sp,bp /* save stackptr */
+ sub $(4*4),sp /* create stackframe */
+ and $0xfffffff0,sp /* align stack to 16-byte */
+
+ mov t0,0*4(sp) /* save registers */
+ mov s1,1*4(sp)
+ mov s2,2*4(sp)
+
+ mov sp,s1 /* save stack pointer */
+
+ mov 3*4(bp),t0 /* address of data structure */
+ mov 4*4(bp),itmp1 /* number of stack arguments */
+
+ cmp $0,itmp1
+ je L_asm_vm_call_method_stack_copy_done
+
+ mov itmp1,itmp2
+ add $1,itmp2 /* keep stack 16-byte aligned */
+ and $0xfffffffe,itmp2
+ shl $3,itmp2 /* calculate stack size */
+ sub itmp2,sp /* create stack frame */
+ mov sp,itmp2 /* temporary stack pointer */
+
+L_asm_vm_call_method_stack_copy_loop:
+ mov 0(t0),itmp3 /* load argument */
+ mov itmp3,0(itmp2) /* store argument on stack */
+ mov 4(t0),itmp3
+ mov itmp3,4(itmp2)
+
+ sub $1,itmp1 /* subtract 1 argument */
+ add $8,t0 /* set address of next argument */
+ add $8,itmp2 /* increase SP */
+
+ cmp $0,itmp1
+ jg L_asm_vm_call_method_stack_copy_loop
+
+L_asm_vm_call_method_stack_copy_done:
+ lea (2*4-256)(bp),mptr /* We subtract 256 to force the next */
+ /* move instruction to have a 32-bit */
+ /* offset. */
+
+ mov (0*4+256)(mptr),itmp3 /* method call as in Java */
+ call *itmp3 /* call JIT compiler */
+
+L_asm_vm_call_method_return:
+ mov s1,sp /* restore stackpointer */
+
+ mov 0*4(sp),t0 /* restore registers */
+ mov 1*4(sp),s1
+ mov 2*4(sp),s2
+
+ leave
+ ret
+
+asm_vm_call_method_exception_handler:
+ push xptr /* pass exception pointer */
+ call builtin_throw_exception
+ add $4,sp
+asm_vm_call_method_end:
+ jmp L_asm_vm_call_method_return
+
+
+/* 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.
- movl sizejniblock*2+offjniitem+4(%ebp),%ebx
- movl %ebx,20(%esp)
- movl sizejniblock*2+offjniitem(%ebp),%ebx
- movl %ebx,16(%esp)
-
-
- movl sizejniblock+offjniitem+4(%ebp),%ebx
- movl %ebx,12(%esp)
- movl sizejniblock+offjniitem(%ebp),%ebx
- movl %ebx,8(%esp)
-
- movl offjniitem+4(%ebp),%ebx
- movl %ebx,4(%esp)
- movl offjniitem(%ebp),%ebx
- movl %ebx,0(%esp)
-
- movl %eax,%ebp
- movl 8(%ebp),%eax /* move function pointer to %eax */
+*******************************************************************************/
- lea asm_call_jit_compiler,%ecx
- call *%ecx /* call JIT compiler */
-
-calljava_jit3:
-calljava_return3:
-calljava_ret3:
- leave
- ret
+asm_call_jit_compiler:
+L_asm_call_jit_compiler: /* required for PIC code */
+ sub $(4*4),sp /* keep stack 16-byte aligned */
-calljava_xhandler3:
- pushl %eax /* pass exception pointer */
- call builtin_throw_exception
- addl $4,%esp
- addl $32,%esp
- popl %ebp
- ret
+ mov itmp1,0*4(sp) /* pass methodinfo pointer */
+ mov mptr,1*4(sp) /* pass method pointer */
+ mov sp,itmp2 /* pass java sp */
+ add $((1+4)*4),itmp2
+ mov itmp2,2*4(sp)
+ mov 4*4(sp),itmp3 /* pass java ra */
+ mov itmp3,3*4(sp)
+ call jit_asm_compile
+ add $(4*4),sp /* remove stack frame */
+ test v0,v0 /* check for exception */
+ je L_asm_call_jit_compiler_exception
+ jmp *v0 /* ...and now call the new method */
+L_asm_call_jit_compiler_exception:
+ call exceptions_get_and_clear_exception
+ /* v0 == xptr */
+ pop xpc /* get return address */
+ sub $2,xpc /* faulting address is ra - 2 */
+ jmp L_asm_handle_exception
-/****************** function asm_call_jit_compiler *****************************
-* *
-* invokes the compiler for untranslated JavaVM methods. *
+/* asm_handle_exception ********************************************************
* *
-* 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 *
+* 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_call_jit_compiler:
- push %ecx
- push %ebx /* save register */
- push %ebp
-
- mov 12(%esp),%ebp /* get return address (2 push) */
- mov -1(%ebp),%bl /* get function code */
- cmp $0xd2,%bl /* called with `call *REG_ITMP2' (%edx)? */
- jne L_not_static_special
-
- sub $6,%ebp /* calculate address of immediate */
- jmp L_call_jit_compile
-
-L_not_static_special:
- cmp $0xd0,%bl /* called with `call *REG_ITMP1' (%eax) */
- jne L_not_virtual_interface
+asm_handle_nat_exception:
+ add $4,sp /* clear return address of native stub*/
- sub $6,%ebp /* calculate address of offset */
- mov (%ebp),%ebp /* get offset */
- add %edx,%ebp /* add base address to get method address */
- jmp L_call_jit_compile
+asm_handle_exception:
+L_asm_handle_exception: /* required for PIC code */
+ sub $((ARG_CNT+TMP_CNT+3)*4),sp /* keep stack 16-byte aligned */
-L_not_virtual_interface: /* a call from asm_calljavamethod */
- xor %ebp,%ebp
-
-L_call_jit_compile:
- push %ebp /* save address for method pointer */
+ SAVE_ARGUMENT_REGISTERS(0) /* we save arg and temp registers in */
+ SAVE_TEMPORARY_REGISTERS(ARG_CNT) /* case this is a leaf method */
- push %eax /* push methodpointer on stack */
- call jit_compile
- add $4,%esp
+ mov $((ARG_CNT+TMP_CNT+3)*4),itmp3 /* prepare a3 for handle_exception */
+ mov $1,t0 /* set maybe-leaf flag */
- pop %ebp /* restore address for method pointer */
- test %ebp,%ebp /* is address == 0 (asm_calljavamethod) */
- je L_call_method
-
- mov %eax,(%ebp) /* and now save the new pointer */
+L_asm_handle_exception_stack_loop:
+ sub $(12*4),sp /* keep stack 16-byte aligned */
+ mov xptr,4*4(sp) /* save exception pointer */
+ mov xpc,5*4(sp) /* save exception pc */
+ add sp,itmp3 /* calculate Java sp into a3... */
+ add $(12*4),itmp3
+ mov itmp3,7*4(sp) /* ...and save it */
+ mov t0,8*4(sp) /* save maybe-leaf flag */
-L_call_method:
- pop %ebp
- pop %ebx /* restore registers */
- pop %ecx
-
- jmp *%eax /* ...and now call the new method */
+ mov xpc,0*4(sp) /* pass exception pc */
+ call codegen_get_pv_from_pc
+ mov v0,6*4(sp) /* save data segment pointer */
+ mov 4*4(sp),itmp3 /* pass exception pointer */
+ mov itmp3,0*4(sp)
+ mov 5*4(sp),itmp3 /* pass exception pc */
+ mov itmp3,1*4(sp)
+ mov v0,2*4(sp) /* pass data segment pointer */
+ mov 7*4(sp),itmp3 /* pass Java stack pointer */
+ mov itmp3,3*4(sp)
+ call exceptions_handle_exception
+ test v0,v0
+ jz L_asm_handle_exception_not_catched
-/****************** function asm_dumpregistersandcall **************************
-* *
-* This funtion saves all callee saved registers and calls the function *
-* which is passed as parameter. *
-* *
-* This function is needed by the garbage collector, which needs to access *
-* all registers which are stored on the stack. Unused registers are *
-* cleared to avoid interferances with the GC. *
-* *
-* void asm_dumpregistersandcall (functionptr f); *
-* *
-*******************************************************************************/
+ mov v0,xpc /* move handlerpc into xpc */
+ mov 4*4(sp),xptr /* restore exception pointer */
+ mov 8*4(sp),t0 /* get maybe-leaf flag */
+ add $(12*4),sp /* free stackframe */
-asm_dumpregistersandcall:
- xor %eax,%eax
- mov %eax,(%eax)
-
- push %ebx
- push %ebp
- push %esi
- push %edi
-
- mov 8(%ebp),%eax /* load function pointer */
- call *%eax /* call function */
-
- pop %edi
- pop %esi
- pop %ebp
- pop %ebx
-
- ret
-
+ test t0,t0 /* test for maybe-leaf flag */
+ jz L_asm_handle_exception_no_leaf
-/********************* 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); *
-* *
-*******************************************************************************/
+ RESTORE_ARGUMENT_REGISTERS(0) /* if this is a leaf method, we have */
+ RESTORE_TEMPORARY_REGISTERS(ARG_CNT)/* to restore arg and temp registers */
-asm_handle_builtin_exception:
- add $4,%esp /* clear return address of this call */
- mov (%esp),%eax /* get exceptionptr */
- leave /* leave builtin function */
- mov (%esp),%edx /* get exceptionpc */
- sub $2,%edx /* size of builtin call */
- jmp asm_handle_exception
-
-asm_handle_nat_exception:
- add $4,%esp /* clear return address of native stub */
-
-asm_handle_exception:
- push %eax
- push %edx /* get the data segment ptr */
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
- call cast_lock
-#endif
- call findmethod
- mov %eax,%ecx
- pop %edx
- pop %eax
-
- push %ebp
- mov %esp,%ebp
-
- push %eax /* save exception pointer */
-/* subl $2,%edx */
- push %edx /* save exception pc */
- push %ecx /* save data segment pointer */
-
- push %ebx
- push %esi
- push %edi
-
-ex_stack_loop:
- sub $16,%esp
+ add $((ARG_CNT+TMP_CNT+3)*4),sp /* remove maybe-leaf stackframe */
- movl %eax,(%esp) /* exception pointer */
+L_asm_handle_exception_no_leaf:
+ jmp *xpc /* jump to exception handler */
- movl MethodPointer(%ecx),%eax /* method pointer */
- movl %eax,4(%esp)
-
- movl %edx,8(%esp) /* exception pc */
- movl $1,12(%esp) /* set no unwind flag */
- call builtin_trace_exception
+L_asm_handle_exception_not_catched:
+ mov 4*4(sp),xptr /* restore exception pointer */
+ mov 6*4(sp),itmp3 /* restore data segment pointer */
+ mov 8*4(sp),t0 /* get maybe-leaf flag */
+ add $(12*4),sp /* free stackframe */
- addl $16,%esp
+ test t0,t0
+ jz L_asm_handle_exception_no_leaf_stack
- movl -12(%ebp),%esi /* %esi = data segment pointer */
- movl ExTableSize(%esi),%ecx /* %ecx = exception table size */
- test %ecx,%ecx /* if empty table skip */
- je empty_table
+ add $((ARG_CNT+TMP_CNT+3)*4),sp /* remove maybe-leaf stackframe */
+ xor t0,t0 /* clear the maybe-leaf flag */
- lea ExTableStart(%esi),%edi /* %edi = start of exception table */
- movl -4(%ebp),%eax /* get xptr */
-
-ex_table_loop:
- movl -8(%ebp),%edx /* get xpc */
-
- movl ExStartPC(%edi),%ebx /* %ebx = exception start pc */
- cmpl %edx,%ebx /* %ebx = (startpc <= xpc) */
- jg ex_table_cont /* if (false) continue */
- movl ExEndPC(%edi),%ebx /* %ebx = exception end pc */
- cmpl %ebx,%edx /* %ebx = (xpc < endpc) */
- jge ex_table_cont /* if (false) continue */
- movl ExCatchType(%edi),%ebx /* arg1 = exception catch type */
- test %ebx,%ebx /* NULL catches everything */
- je ex_handle_it
-
- movl offobjvftbl(%eax),%esi /* %esi = vftblptr(xptr) */
- movl offclassvftbl(%ebx),%ebx /* %ebx = vftblptr(catchtype) class (not obj) */
- movl offbaseval(%esi),%esi /* %esi = baseval(xptr) */
- movl offbaseval(%ebx),%edx /* %edx = baseval(catchtype) */
- movl offdiffval(%ebx),%ebx /* %ebx = diffval(catchtype) */
- subl %edx,%esi /* %esi = baseval(xptr) - baseval(catchtype) */
- cmpl %ebx,%esi /* xptr is instanceof catchtype */
- ja ex_table_cont
-
-ex_handle_it:
- movl ExHandlerPC(%edi),%edx
-
- popl %edi
- popl %esi
- popl %ebx
-
- popl %eax /* pop %ecx (dummy) */
- popl %eax /* pop %edx (dummy) */
- popl %eax /* pop %eax */
-
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
- call cast_unlock
-#endif
-
- leave
+L_asm_handle_exception_no_leaf_stack:
+ mov FrameSize(itmp3),itmp2 /* get frame size */
+ add sp,itmp2 /* pointer to save area */
- jmp *%edx
+ push xptr /* we are out of registers */
-ex_table_cont:
- lea ExEntrySize(%edi),%edi
- decl %ecx
- test %ecx,%ecx
- jg ex_table_loop
-
-empty_table:
- popl %edi
- popl %esi
- popl %ebx
- popl %ecx /* restore data segment pointer */
- popl %edx
- popl %eax /* restore exception pointer */
- popl %ebp
-
- movl %eax,%edi /* save exception pointer */
-
-ex_already_cleared:
- movl IsSync(%ecx),%eax /* %eax = SyncOffset */
- test %eax,%eax /* if zero no monitorexit */
- je no_monitor_exit
-
- addl %esp,%eax
- movl -8(%eax),%eax
- pusha /* save regs */
- pushl %eax
- call builtin_monitorexit
- addl $4,%esp
- popa /* restore regs */
-
-no_monitor_exit:
- movl FrameSize(%ecx),%eax /* %eax = frame size */
- addl %eax,%esp /* unwind stack */
- movl %esp,%eax /* %eax = pointer to save area */
-
- movl IntSave(%ecx),%edx /* %edx = saved int register count */
- test %edx,%edx
- je noint
- cmpl $1,%edx
- je int1
-
-int2:
- movl -16(%eax),%ebx
+ mov IntSave(itmp3),itmp1 /* itmp1 = saved int register count */
+ test itmp1,itmp1
+ je noint
+ cmp $1,itmp1
+ je int1
+ cmp $2,itmp1
+ je int2
+
+ mov -3*8(itmp2),s0
+int2:
+ mov -2*8(itmp2),s1
int1:
- movl -8(%eax),%ebp
+ mov -1*8(itmp2),s2
- shll $3,%edx /* multiply by 8 bytes */
- subl %edx,%eax
+ shl $2,itmp1 /* multiply by 4 bytes */
+ sub itmp1,itmp2
noint:
- movl FltSave(%ecx),%edx /* %edx = saved flt register count */
- test %edx,%edx
- je noflt
- cmpl $1,%edx
- je flt1
- cmpl $2,%edx
- je flt2
- cmpl $3,%edx
- je flt3
-
-flt4:
- fldl -32(%eax)
- fstp %st(1)
+#if 0
+ mov FltSave(itmp3),itmp1 /* itmp1 = saved flt register count */
+ test itmp1,itmp1
+ je noflt
+
+ cmp $1,itmp1
+ je flt1
+ cmp $2,itmp1
+ je flt2
+ cmp $3,itmp1
+ je flt3
+
+ fldl -4*8(itmp2)
+ fstp %st(1)
+flt3:
+ fldl -3*8(itmp2)
+ fstp %st(2)
+flt2:
+ fldl -2*8(itmp2)
+ fstp %st(3)
+flt1:
+ fldl -1*8(itmp2)
+ fstp %st(4)
+
+noflt:
+#endif
+ pop xptr /* restore exception pointer */
+ mov FrameSize(itmp3),itmp2 /* get frame size */
+ add itmp2,sp /* unwind stack */
-flt3:
- fldl -24(%eax)
- fstp %st(2)
-
-flt2:
- fldl -16(%eax)
- fstp %st(3)
-
-flt1:
- fldl -8(%eax)
- fstp %st(4)
-
-noflt:
- popl %edx /* the new xpc is return address */
- subl $2,%edx
-
- pushl %edx
- pushl %ebx
- pushl %ebp
- pushl %esi
- pushl %edi
-
- pushl %edx /* get the new data segment ptr */
- call findmethod
- movl %eax,%ecx
- addl $4,%esp
-
- popl %edi
- popl %esi
- popl %ebp
- popl %ebx
- popl %edx
-
- movl %edi,%eax /* restore saved exception pointer */
-
- pushl %ebp
- movl %esp,%ebp
-
- pushl %eax /* save exception pointer */
- pushl %edx /* save exception pc */
- pushl %ecx /* save data segment pointer */
- pushl %ebx
- pushl %esi
- pushl %edi
-
- jmp ex_stack_loop
+ pop xpc /* the new xpc is return address */
+ sub $2,xpc /* subtract 2-bytes for call */
+
+ xor itmp3,itmp3 /* prepare a3 for handle_exception */
+
+ jmp L_asm_handle_exception_stack_loop
-/********************* function asm_builtin_monitorenter ***********************
-* *
-* Does null check and calls monitorenter or throws an exception *
-* *
+/* asm_abstractmethoderror *****************************************************
+
+ Creates and throws an AbstractMethodError.
+
*******************************************************************************/
-asm_builtin_monitorenter:
- cmpl $0,4(%esp)
- je nb_monitorenter /* if (null) throw exception */
- jmp builtin_monitorenter /* else call builtin_monitorenter */
+asm_abstractmethoderror:
+ sub $(3*4),sp /* keep stack 16-byte aligned */
+ mov sp,itmp1 /* pass java sp */
+ add $((1+3)*4),itmp1
+ mov itmp1,0*4(sp)
+ mov 3*4(sp),itmp2 /* pass exception address */
+ sub $2,itmp2
+ mov itmp2,1*4(sp)
+ call exceptions_asm_new_abstractmethoderror
+ /* exception pointer is return value */
+ add $(3*4),sp /* remove stack frame */
-nb_monitorenter:
- popl %edx /* delete return address */
- subl $2,%edx /* faulting address is return adress - 2 */
- movl proto_java_lang_NullPointerException,%eax
- jmp asm_handle_exception
-
+ pop xpc /* get exception address */
+ sub $2,xpc /* exception address is ra - 2 */
+ jmp L_asm_handle_exception
-/********************* function asm_builtin_monitorexit ************************
-* *
-* Does null check and calls monitorexit or throws an exception *
-* *
-*******************************************************************************/
-asm_builtin_monitorexit:
- cmpl $0,4(%esp)
- je nb_monitorexit /* if (null) throw exception */
- jmp builtin_monitorexit /* else call builtin_monitorenter */
+/* asm_patcher_wrapper *********************************************************
-nb_monitorexit:
- popl %edx /* delete return address */
- subl $2,%edx /* faulting address is return adress - 2 */
- movl proto_java_lang_NullPointerException,%eax
- jmp asm_handle_exception
+ XXX
+ Stack layout:
+ 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)
+ 4 unresolved field reference
+ 0 patcher function pointer to call
-/************************ function asm_builtin_ldiv ****************************
-* *
-* Does null check and calls ldiv or throws an exception *
-* *
*******************************************************************************/
-asm_builtin_ldiv:
- movl 12(%esp),%eax
- orl 16(%esp),%eax
- test %eax,%eax /* if (null) throw exception */
- je nb_ldiv
+asm_patcher_wrapper:
+ sub $((1+4+4)*4),sp /* keep stack 16-byte aligned */
- jmp builtin_ldiv
+ mov itmp1,(0+4)*4(sp) /* save itmp1 and itmp2 */
+ mov itmp2,(1+4)*4(sp)
-nb_ldiv:
- popl %edx /* delete return address */
- subl $2,%edx /* faulting address is return adress - 2 */
-
- movl proto_java_lang_ArithmeticException,%eax
- jmp asm_handle_exception
-
+ mov sp,itmp1 /* pass SP of patcher stub */
+ add $((1+4+4)*4),itmp1
+ mov itmp1,0*4(sp)
+ movl $0,1*4(sp) /* pass PV (if NULL, use findmethod) */
+ movl $0,2*4(sp) /* pass RA (it's on the stack) */
+ call patcher_wrapper
+ mov v0,itmp3 /* save return value */
-/************************ function asm_builtin_lrem ****************************
-* *
-* Does null check and calls lrem or throws an exception *
-* *
-*******************************************************************************/
+ mov (0+4)*4(sp),itmp1 /* restore itmp1 and itmp2 */
+ mov (1+4)*4(sp),itmp2
-asm_builtin_lrem:
- movl 12(%esp),%eax
- orl 16(%esp),%eax
- test %eax,%eax /* if (null) throw exception */
- je nb_lrem
+ test itmp3,itmp3 /* exception thrown? */
+ jne L_asm_patcher_wrapper_exception
- jmp builtin_lrem
+ mov (5+1+4+4)*4(sp),itmp3 /* restore itmp3 */
+ add $((6+1+4+4)*4),sp /* remove stack frame, keep RA */
-nb_lrem:
- popl %edx /* delete return address */
- subl $2,%edx /* faulting address is return adress - 2 */
-
- movl proto_java_lang_ArithmeticException,%eax
- jmp asm_handle_exception
-
+ ret /* jump to new patched code */
-/************************ function asm_builtin_x2x *****************************
-* *
-* Wrapper functions for corner cases *
-* *
-*******************************************************************************/
+L_asm_patcher_wrapper_exception:
+ add $((6+1+4+4)*4),sp /* remove stack frame, keep RA */
+ mov itmp3,xptr /* get exception */
+ pop xpc /* get and remove return address */
+ jmp L_asm_handle_exception
-asm_builtin_f2i:
- sub $4,%esp
- fsts (%esp)
- call builtin_f2i
- add $4,%esp
- ret
+#if defined(ENABLE_REPLACEMENT)
-asm_builtin_d2i:
- sub $8,%esp
- fstl (%esp)
- call builtin_d2i
- add $8,%esp
- ret
+/* asm_replacement_out *********************************************************
-asm_builtin_f2l:
- sub $4,%esp
- fsts (%esp)
- call builtin_f2l
- add $4,%esp
- ret
+ This code is jumped to from the replacement-out stubs that are executed
+ when a thread reaches an activated replacement point.
-asm_builtin_d2l:
- sub $8,%esp
- fstl (%esp)
- call builtin_d2l
- add $8,%esp
- ret
-
-
-/*********************** function new_builtin_checkcast ************************
-* *
-* Does the cast check and eventually throws an exception *
-* *
-*******************************************************************************/
+ 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.
-asm_builtin_checkcast:
- xorl %eax,%eax
- movl $0,(%eax)
- ret
+ Stack layout:
+ 4 start of stack inside method to replace
+ 0 rplpoint * info on the replacement point that was reached
-
-/******************* function asm_builtin_checkarraycast ***********************
-* *
-* Does the cast check and eventually throws an exception *
-* *
*******************************************************************************/
-asm_builtin_checkarraycast:
- subl $8,%esp /* build stack frame (2 * 4 bytes) */
+/* some room to accomodate changes of the stack frame size during replacement */
+ /* XXX we should find a cleaner solution here */
+#define REPLACEMENT_ROOM 512
- movl 12(%esp),%eax /* 8 (frame) + 4 (return) */
- movl %eax,(%esp) /* save object pointer */
+asm_replacement_out:
+ /* create stack frame */
+ sub $(sizeexecutionstate + REPLACEMENT_ROOM),sp
- movl 20(%esp),%eax
- movl %eax,4(%esp)
+ /* save registers in execution state */
+ mov %eax,(EAX*4+offes_intregs)(sp)
+ mov %ebx,(EBX*4+offes_intregs)(sp)
+ mov %ecx,(ECX*4+offes_intregs)(sp)
+ mov %edx,(EDX*4+offes_intregs)(sp)
+ mov %esi,(ESI*4+offes_intregs)(sp)
+ mov %edi,(EDI*4+offes_intregs)(sp)
+ mov %ebp,(EBP*4+offes_intregs)(sp)
+ movl $0 ,(ESP*4+offes_intregs)(sp) /* not used */
- call builtin_checkarraycast /* builtin_checkarraycast */
-
- test %eax,%eax /* if (false) throw exception */
- je nb_carray_throw
+ /* calculate sp of method */
+ mov sp,itmp1
+ add $(sizeexecutionstate + REPLACEMENT_ROOM + 4),itmp1
+ mov itmp1,(offes_sp)(sp)
- movl 12(%esp),%eax /* return object pointer */
- addl $8,%esp
- ret
+ /* pv must be looked up via AVL tree */
+ movl $0,(offes_pv)(sp)
-nb_carray_throw:
- addl $8,%esp
-
- popl %edx /* delete return address */
- subl $2,%edx /* faulting address is return adress - 2 */
-
- movl proto_java_lang_ClassCastException,%eax
- jmp asm_handle_exception
+ /* 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 */
-
-/******************* function asm_builtin_newarray *****************************
-* *
-* Does the cast check and eventually throws an exception *
-* *
-*******************************************************************************/
-asm_builtin_newarray:
- subl $8,%esp /* build stack frame (2 * 4 bytes) */
+/* asm_replacement_in **********************************************************
- movl 12(%esp),%eax
- movl %eax,(%esp)
+ This code writes the given execution state and jumps to the replacement
+ code.
- movl 20(%esp),%eax
- movl %eax,4(%esp)
+ This function never returns!
- call builtin_newarray
-
- addl $8,%esp
- ret
+ C prototype:
+ void asm_replacement_in(executionstate *es, replace_safestack_t *st);
-
-/******************* function asm_builtin_aastore ******************************
-* *
-* Does the cast check and eventually throws an exception *
-* *
*******************************************************************************/
-asm_builtin_aastore:
- subl $12,%esp /* build stack frame (3 * 4 bytes) */
+asm_replacement_in:
+ /* get arguments */
+ mov 8(sp),%esi /* replace_safestack_t *st */
+ mov 4(sp),%ebp /* executionstate *es == safe stack */
- movl 16(%esp),%eax /* 12 (frame) + 4 (return) */
- test %eax,%eax /* if null pointer throw exception */
- je nb_aastore_null
+ /* switch to the safe stack and build a stack frame */
+ mov %ebp,sp
+ sub $(1*4),sp
- movl offarraysize(%eax),%edx /* load size */
- movl 24(%esp),%ecx /* index */
- cmpl %edx,%ecx /* do bound check */
- ja nb_aastore_bound /* if out of bounds throw exception */
+ /* call replace_build_execution_state(st) */
+ mov %esi,(0*4)(sp)
+ call replace_build_execution_state
- shll $2,%ecx /* index * 4 */
- addl %eax,%ecx /* add index * 4 to arrayref */
-
- movl %ecx,8(%esp) /* save store position */
-
- movl 16(%esp),%eax /* 12 (frame) + 4 (return) */
- movl %eax,(%esp)
+ /* set new sp */
+ mov (offes_sp)(%ebp),sp
- movl 32(%esp),%eax /* object is second argument */
- movl %eax,4(%esp)
-
- call builtin_canstore /* builtin_canstore(arrayref,object) */
+ /* push address of new code */
+ push (offes_pc)(%ebp)
- test %eax,%eax /* if (false) throw exception */
- je nb_aastore_throw
+ /* allocate an executionstate_t on the stack */
+ sub $(sizeexecutionstate),sp
- movl 32(%esp),%eax
- movl 8(%esp),%ecx
- movl %eax,offobjarrdata(%ecx)/* store objectptr in array */
-
- addl $12,%esp
- ret
+ /* call replace_free_safestack(st,& of allocated executionstate_t) */
+ push sp /* tmpes */
+ push %esi /* st */
+ call replace_free_safestack
+ add $(2*4),sp
-nb_aastore_null:
- addl $12,%esp
- popl %edx /* delete return address */
- subl $2,%edx /* faulting address is return adress - 2 */
-
- movl proto_java_lang_NullPointerException,%eax
- jmp asm_handle_exception
+ /* copy registers from execution state */
+ mov (EAX*4+offes_intregs)(sp),%eax
+ mov (EBX*4+offes_intregs)(sp),%ebx
+ mov (ECX*4+offes_intregs)(sp),%ecx
+ mov (EDX*4+offes_intregs)(sp),%edx
+ mov (ESI*4+offes_intregs)(sp),%esi
+ mov (EDI*4+offes_intregs)(sp),%edi
+ mov (EBP*4+offes_intregs)(sp),%ebp
-nb_aastore_bound:
- addl $12,%esp
- popl %edx /* delete return address */
- subl $2,%edx /* faulting address is return adress - 2 */
-
- movl proto_java_lang_ArrayIndexOutOfBoundsException,%eax
- jmp asm_handle_exception
-
-nb_aastore_throw:
- addl $12,%esp
- popl %edx /* delete return address */
- subl $2,%edx /* faulting address is return adress - 2 */
-
- movl proto_java_lang_ArrayStoreException,%eax
- jmp asm_handle_exception
+ /* pop the execution state off the stack */
+ add $(sizeexecutionstate),sp
-
-/******************* function asm_builtin_arrayinstanceof **********************
+ /* jump to new code, hold your thumbs! ;) */
+ ret
+
+#endif /* defined(ENABLE_REPLACEMENT) */
+
+
+/************************ function asm_builtin_x2x *****************************
* *
-* Does the instanceof check of arrays *
+* Wrapper functions for corner cases *
* *
*******************************************************************************/
-asm_builtin_arrayinstanceof:
- subl $8,%esp /* build stack frame (2 * 4 bytes) */
+asm_builtin_f2i:
+ sub $(3*4),%esp
+ fsts (%esp)
+ call builtin_f2i
+ add $(3*4),%esp
+ ret
- movl 12(%esp),%eax
- movl %eax,(%esp)
+asm_builtin_d2i:
+ sub $(3*4),%esp
+ fstl (%esp)
+ call builtin_d2i
+ add $(3*4),%esp
+ ret
- movl 20(%esp),%eax
- movl %eax,4(%esp)
+asm_builtin_f2l:
+ sub $(3*4),%esp
+ fsts (%esp)
+ call builtin_f2l
+ add $(3*4),%esp
+ ret
- call builtin_arrayinstanceof
-
- addl $8,%esp
- ret
+asm_builtin_d2l:
+ sub $(3*4),%esp
+ fstl (%esp)
+ call builtin_d2l
+ add $(3*4),%esp
+ ret
-
-/******************* function asm_initialize_thread_stack **********************
-* *
-* initialized a thread stack *
-* (to)->restorePoint = asm_initialize_thread_stack((u1*)(func), (to)->stackEnd)*
-* *
-*******************************************************************************/
-asm_initialize_thread_stack:
- movl 8(%esp),%eax /* (to)->stackEnd */
- subl $36,%eax /* 4 bytes * 8 regs + 4 bytes func */
+/* asm_compare_and_swap ********************************************************
- xorl %edx,%edx
- movl %edx,0(%eax)
- movl %edx,4(%eax)
- movl %edx,8(%eax)
- movl %edx,12(%eax)
- movl %edx,16(%eax)
- movl %edx,20(%eax)
- movl %edx,24(%eax)
- movl %edx,28(%eax)
+ Does an atomic compare and swap. Required for the lock
+ implementation.
- movl 4(%esp),%edx /* save (u1*) (func) */
- movl %edx,32(%eax)
+ Atomically do the following: Check if the location still contains
+ `oldval`. If so, replace it by `newval` and return `oldval`.
- ret /* return restorepoint in %eax */
+ RETURN VALUE:
+ the old value at *p
+ long compare_and_swap(volatile long *p, long oldval, long newval);
-/******************* function asm_perform_threadswitch *************************
-* *
-* void asm_perform_threadswitch (u1 **from, u1 **to, u1 **stackTop); *
-* *
-* performs a threadswitch *
-* *
*******************************************************************************/
-asm_perform_threadswitch:
- subl $36,%esp
-
- movl %eax,0(%esp)
- movl %edx,4(%esp)
- movl %ecx,8(%esp)
- movl %ebx,12(%esp)
- movl %esp,16(%esp)
- movl %ebp,20(%esp)
- movl %esi,24(%esp)
- movl %edi,28(%esp)
-
- movl 36(%esp),%eax /* save current return address */
- movl %eax,32(%esp)
-
- movl 40(%esp),%eax /* first argument **from */
- movl %esp,0(%eax)
-
- movl 48(%esp),%eax /* third argument **stackTop */
- movl %esp,0(%eax)
-
- movl 44(%esp),%eax /* second argument **to */
- movl 0(%eax),%esp /* load new stack pointer */
-
- movl 0(%esp),%eax
- movl 4(%esp),%edx
- movl 8(%esp),%ecx
- movl 12(%esp),%ebx
- /* skip stack pointer */
- movl 20(%esp),%ebp
- movl 24(%esp),%esi
- movl 28(%esp),%edi
-
- addl $32,%esp /* leave return address on stack */
- ret
-
+asm_compare_and_swap:
+ mov 1*4(sp),%ecx /* load p into a register */
+ mov 2*4(sp),%eax /* load oldval into return register */
+ mov 3*4(sp),%edx /* load newval into a register */
+ lock; cmpxchgl %edx,0(%ecx)
+ ret
-/********************* function asm_switchstackandcall *************************
-* *
-* int asm_switchstackandcall (void *stack, void *func, void **stacktopsave, *
-* void *p); *
-* *
-* Switches to a new stack, calls a function and switches back. *
-* a0 new stack pointer *
-* a1 function pointer *
-* a2 pointer to variable where stack top should be stored *
-* a3 pointer to user data, is passed to the function *
-* *
-*******************************************************************************/
-asm_switchstackandcall:
- movl 4(%esp),%edx /* first argument *stack */
- subl $8,%edx /* allocate new stack */
+/* asm_memory_barrier **********************************************************
- movl (%esp),%eax /* save return address on new stack */
- movl %eax,(%edx)
+ A memory barrier for the Java Memory Model.
- movl %esp,4(%edx) /* save old stack pointer on new stack */
+*******************************************************************************/
- movl 12(%esp),%eax /* third argument **stacktopsave */
- movl %esp,(%eax) /* save old stack pointer to variable */
+asm_memory_barrier:
+ lock; add $0,0(sp)
+ ret
- movl 8(%esp),%eax /* load function pointer */
- movl 16(%esp),%ecx /* fourth argument *p */
- movl %edx,%esp /* switch to new stack */
+/* asm_get_cycle_count *********************************************************
- subl $4,%esp
- movl %ecx,0(%esp) /* pass pointer */
- call *%eax /* and call function */
- addl $4,%esp
+ Get the current time-stamp counter from the CPU.
- movl (%esp),%edx /* load return address */
- movl 4(%esp),%esp /* switch to old stack */
- movl %edx,(%esp)
- ret
-
-
-/********************* function asm_getcallingmethod ***************************
-* *
-* classinfo *asm_getcallingmethod (); *
-* *
-* goes back stack frames to get the calling method *
-* *
-* t2 .. sp *
-* t3 .. ra *
-* t4 .. pv *
-* *
*******************************************************************************/
-asm_getcallingmethod:
- xorl %eax,%eax
-/* movl $0,(%eax) */
- ret
+asm_get_cycle_count:
+ rdtsc
+ ret
-/*********************** function asm_builtin_trace ****************************
-* *
-* Intended to be called from the native stub. Saves all argument registers *
-* and calls builtin_trace_args. *
-* *
-*******************************************************************************/
+/* disable exec-stacks ********************************************************/
+
+#if defined(__linux__) && defined(__ELF__)
+ .section .note.GNU-stack,"",%progbits
+#endif
-asm_builtin_trace:
- pusha
- subl $68,%esp /* 4 + 8 * 4 + 68 = 104 */
-
- movl 104(%esp),%eax
- movl 108(%esp),%edx
- movl %eax,(%esp)
- movl %edx,4(%esp)
-
- movl 112(%esp),%eax
- movl 116(%esp),%edx
- movl %eax,8(%esp)
- movl %edx,12(%esp)
-
- movl 120(%esp),%eax
- movl 124(%esp),%edx
- movl %eax,16(%esp)
- movl %edx,20(%esp)
-
- movl 128(%esp),%eax
- movl 132(%esp),%edx
- movl %eax,24(%esp)
- movl %edx,28(%esp)
-
- movl 136(%esp),%eax
- movl 140(%esp),%edx
- movl %eax,32(%esp)
- movl %edx,36(%esp)
-
- movl 144(%esp),%eax
- movl 148(%esp),%edx
- movl %eax,40(%esp)
- movl %edx,44(%esp)
-
- movl 152(%esp),%eax
- movl 156(%esp),%edx
- movl %eax,48(%esp)
- movl %edx,52(%esp)
-
- movl 160(%esp),%eax
- movl 164(%esp),%edx
- movl %eax,56(%esp)
- movl %edx,60(%esp)
-
- movl 168(%esp),%eax
- movl %eax,64(%esp)
-
- call builtin_trace_args
- addl $68,%esp
-
- popa
- ret
-
-
-/********************* function asm_builtin_exittrace **************************
-* *
-* Intended to be called from the native stub. Saves return value and calls *
-* builtin_displaymethodstop. *
-* *
-*******************************************************************************/
-asm_builtin_exittrace:
- pusha
- subl $24,%esp
-
- movl 60(%esp),%eax /* 4 + 8 * 4 + 24 = 60 */
- movl %eax,(%esp)
-
- movl 64(%esp),%eax
- movl 68(%esp),%edx
- movl %eax,4(%esp)
- movl %edx,8(%esp)
-
- movl 72(%esp),%eax
- movl 76(%esp),%edx
- movl %eax,12(%esp)
- movl %edx,16(%esp)
-
- movl 80(%esp),%eax
- movl %eax,20(%esp)
-
- call builtin_displaymethodstop
- addl $24,%esp
-
- popa
- ret
-
-asm_xadd:
- mov 4(%esp),%ecx
- mov 8(%esp),%eax
- lock
- xaddl %eax,0(%ecx)
- ret
+/*
+ * 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:
+ */