-/* jit/mips/asmpart.S - Java-C interface functions for mips
+/* src/vm/jit/mips/asmpart.S - Java-C interface functions for MIPS
- Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
- Institut f. Computersprachen, TU Wien
- R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser, M. Probst,
- S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich,
- J. Wenninger
+ Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+ C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
+ E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
+ J. Wenninger, Institut f. Computersprachen - TU Wien
This file is part of CACAO.
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., 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA.
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
- Contact: cacao@complang.tuwien.ac.at
+ Contact: cacao@cacaojvm.org
Authors: Andreas Krall
- $Id: asmpart.S 824 2004-01-03 14:31:04Z twisti $
+ Changes: Christian Thalinger
+ Edwin Steiner
+
+ $Id: asmpart.S 7455 2007-03-05 15:46:53Z tbfg $
*/
-#include "offsets.h"
-
-#define zero $0
-#define itmp1 $1
-#define v0 $2
-#define itmp2 $3
-#define a0 $4
-#define a1 $5
-#define a2 $6
-#define a3 $7
-
-#define a4 $8
-#define a5 $9
-#define a6 $10
-#define a7 $11
-#define t0 $12
-#define t1 $13
-#define t2 $14
-#define t3 $15
-
-#define s0 $16
-#define s1 $17
-#define s2 $18
-#define s3 $19
-#define s4 $20
-#define s5 $21
-#define s6 $22
-#define s7 $23
-
-#define t4 $24
-#define itmp3 $25
-#define k0 $26
-#define k1 $27
-
-#define gp $28
-#define sp $29
-#define s8 $30
-#define ra $31
-
-#define pv s8
-#define t9 itmp3
-
-#define xptr itmp1
-#define xpc itmp2
-#define mptr itmp3
-#define mptrreg 25
-
-#define fv0 $f0
-#define ft0 $f1
-#define ft1 $f2
-#define ft2 $f3
-#define ft3 $f4
-#define ft4 $f5
-#define ft5 $f6
-#define ft6 $f7
-
-#define ft7 $f8
-#define ft8 $f9
-#define ft9 $f10
-#define ft10 $f11
-#define fa0 $f12
-#define fa1 $f13
-#define fa2 $f14
-#define fa3 $f15
-
-#define fa4 $f16
-#define fa5 $f17
-#define fa6 $f18
-#define fa7 $f19
-#define ft11 $f20
-#define ft12 $f21
-#define ft13 $f22
-#define ft14 $f23
-
-#define fs0 $f24
-#define ft15 $f25
-#define fs1 $f26
-#define ft16 $f27
-#define fs2 $f28
-#define ft17 $f29
-#define fs3 $f30
-#define ft18 $f31
-
-#define fss0 $f20
-#define fss1 $f22
-#define fss2 $f25
-#define fss3 $f27
-#define fss4 $f29
-#define fss5 $f31
-
-#define aaddu daddu
-#define asubu dsubu
-#define aaddiu daddiu
-#define ald ld
-#define ast sd
-#define ala dla
-#define asll dsll
-#define ashift 3
-
-#define MethodPointer -8
-#define FrameSize -12
-#define IsSync -16
-#define IsLeaf -20
-#define IntSave -24
-#define FltSave -28
-#define ExTableSize -32
-#define ExTableStart -32
-
-#define ExEntrySize -32
-#define ExStartPC -8
-#define ExEndPC -16
-#define ExHandlerPC -24
-#define ExCatchType -32
+#include "config.h"
+
+#include "vm/jit/mips/md-abi.h"
+#include "vm/jit/mips/md-asm.h"
+#include "vm/jit/mips/offsets.h"
+
+#include "vm/jit/abi-asm.h"
+#include "vm/jit/methodheader.h"
.text
.set noat
-/********************* exported functions and variables ***********************/
+/* export functions ***********************************************************/
+
+ .globl asm_vm_call_method
+ .globl asm_vm_call_method_int
+ .globl asm_vm_call_method_long
+ .globl asm_vm_call_method_float
+ .globl asm_vm_call_method_double
+ .globl asm_vm_call_method_exception_handler
+ .globl asm_vm_call_method_end
- .globl has_no_x_instr_set
- .globl synchronize_caches
- .globl asm_calljavafunction_asm
.globl asm_call_jit_compiler
- .globl asm_dumpregistersandcall
+
.globl asm_handle_exception
.globl asm_handle_nat_exception
- .globl asm_builtin_checkarraycast
- .globl asm_builtin_checkcast
- .globl asm_builtin_aastore
- .globl asm_builtin_monitorenter
- .globl asm_builtin_monitorexit
- .globl asm_builtin_idiv
- .globl asm_builtin_irem
- .globl asm_builtin_ldiv
- .globl asm_builtin_lrem
- .globl asm_perform_threadswitch
- .globl asm_initialize_thread_stack
- .globl asm_switchstackandcall
- .globl asm_getcallingmethod
-
-
-/*************************** imported functions *******************************/
-
- .globl jit_compile
- .globl builtin_monitorexit
- .globl builtin_throw_exception
- .globl builtin_trace_exception
- .globl class_java_lang_Object
-
-
-/*********************** function has_no_x_instr_set ***************************
-* *
-* determines if the byte support instruction set (21164a and higher) *
-* is available. *
-* *
-*******************************************************************************/
-
- .ent has_no_x_instr_set
-has_no_x_instr_set:
-
- move v0,zero /* result code 0 (not used for MIPS) */
- j ra /* return */
-
- .end has_no_x_instr_set
-
-/********************* function synchronize_caches ****************************/
+ .globl asm_abstractmethoderror
- .ent synchronize_caches
-synchronize_caches:
+ .globl asm_patcher_wrapper
-/* li a0,BCACHE */ /* flush both caches */
-/* li v0,SYS_cacheflush */ /* Syscall number for cacheflush() */
-/* syscall */ /* call cacheflush() */
- j ra /* return */
+#if defined(ENABLE_REPLACEMENT)
+ .globl asm_replacement_out
+ .globl asm_replacement_in
+#endif
- .end synchronize_caches
+ .globl asm_getclassvalues_atomic
+ .globl asm_criticalsections
+ .globl compare_and_swap
-#if 1
-/********************* function asm_calljavafunction ****************************
+/* asm_vm_call_method **********************************************************
* *
* This function calls a Java-method (which possibly needs compilation) *
* with up to 4 address parameters. *
* *
*******************************************************************************/
- .ent asm_calljavafunction_asm
-
-call_name:
+ .ent asm_vm_call_method
.align 3
-asm_calljavafunction_asm:
-
- aaddiu sp,sp,-10*8 /* allocate stack space */
- sd ra,0(sp) /* save return address */
- .set noreorder
- bal call_java_pc
- sd pv,3*8(sp) /* procedure vector */
-call_java_pc:
+#if SIZEOF_VOID_P == 8
+
+ .dword 0 /* catch type all */
+ .dword 0 /* handler pc */
+ .dword 0 /* end pc */
+ .dword 0 /* start pc */
+ .word 1 /* extable size */
+ .word 0 /* 4-byte ALIGNMENT PADDING */
+ .dword 0 /* line number table start */
+ .dword 0 /* line number table size */
+ .word 0 /* 4-byte ALIGNMENT PADDING */
+ .word 0 /* fltsave */
+ .word 0 /* intsave */
+ .word 0 /* isleaf */
+ .word 0 /* IsSync */
+ .word 0 /* frame size */
+ .dword 0 /* codeinfo pointer */
+
+#else /* SIZEOF_VOID_P == 8 */
+
+ .word 0 /* catch type all */
+ .word 0 /* handler pc */
+ .word 0 /* end pc */
+ .word 0 /* start pc */
+ .word 1 /* extable size */
+ .word 0 /* line number table start */
+ .word 0 /* line number table size */
+ .word 0 /* fltsave */
+ .word 0 /* intsave */
+ .word 0 /* isleaf */
+ .word 0 /* IsSync */
+ .word 0 /* frame size */
+ .word 0 /* method pointer (pointer to name) */
+
+#endif /* SIZEOF_VOID_P == 8 */
+
+asm_vm_call_method:
+asm_vm_call_method_int:
+asm_vm_call_method_long:
+asm_vm_call_method_float:
+asm_vm_call_method_double:
+ .set noreorder /* XXX we need to recompute pv */
+
+ aaddiu sp,sp,-12*8 /* allocate stack space (only 11 needed)*/
+ ast ra,0*8(sp) /* save return address */
+
+ bal L_asm_vm_call_method_compute_pv
+ ast pv,1*8(sp) /* procedure vector */
+L_asm_vm_call_method_compute_pv:
aaddiu pv,ra,-4*4
- .set reorder
-
- sdc1 fss0,4*8(sp) /* save non JavaABI saved flt registers */
- sdc1 fss1,5*8(sp)
- sdc1 fss2,6*8(sp)
- sdc1 fss3,7*8(sp)
- sdc1 fss4,8*8(sp)
- sdc1 fss5,9*8(sp)
- sd a0,2*8(sp) /* save method pointer for compiler */
- aaddiu itmp1,sp,16 /* pass pointer to methodptr via itmp1 */
-
- move a0,a1 /* pass the remaining parameters */
- move a1,a2
- move a2,a3
- move a3,a4
+ ast s7,3*8(sp)
+
+#if SIZEOF_VOID_P == 8
+ sdc1 fss0,5*8(sp) /* save non JavaABI saved flt registers */
+ sdc1 fss1,6*8(sp)
+ sdc1 fss2,7*8(sp)
+ sdc1 fss3,8*8(sp)
+ sdc1 fss4,9*8(sp)
+ sdc1 fss5,10*8(sp)
+#endif
+
+ ast a0,4*8(sp) /* save method pointer for compiler */
+
+ move t0,a2 /* address of first block */
+ move s7,a1 /* argument count */
+ blez s7,calljava_argsloaded
+ nop
+
+#if SIZEOF_VOID_P == 8
+
+ ald a0,offvmargdata(t0)
+ ldc1 fa0,offvmargdata(t0)
+ aaddi s7,s7,-1
+ blez s7,calljava_argsloaded
+ nop
+
+ ald a1,offvmargdata+sizevmarg*1(t0)
+ ldc1 fa1,offvmargdata+sizevmarg*1(t0)
+ aaddi s7,s7,-1
+ blez s7,calljava_argsloaded
+ nop
+
+ ald a2,offvmargdata+sizevmarg*2(t0)
+ ldc1 fa2,offvmargdata+sizevmarg*2(t0)
+ aaddi s7,s7,-1
+ blez s7,calljava_argsloaded
+ nop
+
+ ald a3,offvmargdata+sizevmarg*3(t0)
+ ldc1 fa3,offvmargdata+sizevmarg*3(t0)
+ aaddi s7,s7,-1
+ blez s7,calljava_argsloaded
+ nop
+
+ ald a4,offvmargdata+sizevmarg*4(t0)
+ ldc1 fa4,offvmargdata+sizevmarg*4(t0)
+ aaddi s7,s7,-1
+ blez s7,calljava_argsloaded
+ nop
+
+ ald a5,offvmargdata+sizevmarg*5(t0)
+ ldc1 fa5,offvmargdata+sizevmarg*5(t0)
+ aaddi s7,s7,-1
+ blez s7,calljava_argsloaded
+ nop
+
+ ald a6,offvmargdata+sizevmarg*6(t0)
+ ldc1 fa6,offvmargdata+sizevmarg*6(t0)
+ aaddi s7,s7,-1
+ blez s7,calljava_argsloaded
+ nop
+
+ ald a7,offvmargdata+sizevmarg*7(t0)
+ ldc1 fa7,offvmargdata+sizevmarg*7(t0)
+ aaddi s7,s7,-1
+
+#else /* SIZEOF_VOID_P == 8 */
+
+#if WORDS_BIGENDIAN == 1
+ ald a0,offvmargdata+4(t0)
+#else
+ ald a0,offvmargdata(t0)
+#endif
+#if !defined(ENABLE_SOFT_FLOAT)
+ ldc1 fa0,offvmargdata(t0)
+#endif
+ aaddi s7,s7,-1
+ blez s7,calljava_argsloaded
+
+#if WORDS_BIGENDIAN == 1
+ ald a1,offvmargdata+4+sizevmarg*1(t0)
+#else
+ ald a1,offvmargdata+sizevmarg*1(t0)
+#endif
+#if !defined(ENABLE_SOFT_FLOAT)
+ ldc1 fa1,offvmargdata+sizevmarg*1(t0)
+#endif
+ aaddi s7,s7,-1
+ blez s7,calljava_argsloaded
+
+#if WORDS_BIGENDIAN == 1
+ ald a2,offvmargdata+4+sizevmarg*2(t0)
+#else
+ ald a2,offvmargdata+sizevmarg*2(t0)
+#endif
+ aaddi s7,s7,-1
+ blez s7,calljava_argsloaded
+
+#if WORDS_BIGENDIAN == 1
+ ald a3,offvmargdata+4+sizevmarg*3(t0)
+#else
+ ald a3,offvmargdata+sizevmarg*3(t0)
+#endif
+ aaddi s7,s7,-1
+ blez s7,calljava_argsloaded
+
+#endif /* SIZEOF_VOID_P == 8 */
+
+calljava_argsloaded:
+ move t4,sp /* save stack pointer */
+ blez s7,calljava_nocopy
+ nop
+
+#if SIZEOF_VOID_P == 4
+ aaddiu s7,s7,4 /* add stack space for 4 arguments */
+#endif
+ subu t1,zero,s7 /* remaining argument count (negative) */
+ sll t2,t1,3 /* calculate stackframe size */
+ aaddu sp,sp,t2 /* create stackframe */
+ aaddu t2,t2,t4 /* also set temp sp */
+#if SIZEOF_VOID_P == 4
+ aaddiu t2,t2,4*8 /* skip stack space for 4 arguments */
+ addiu t1,t1,4
+#endif
+
+calljava_copyloop:
+#if SIZEOF_VOID_P == 8
+ ald t3,offvmargdata+sizevmarg*8(t0)
+#else
+# if WORDS_BIGENDIAN == 1
+ ald t3,offvmargdata+4+sizevmarg*4(t0)
+# else
+ ald t3,offvmargdata+sizevmarg*4(t0)
+# endif
+#endif
+ ast t3,0(t2) /* store argument on stack */
+ addi t1,t1,1 /* count 1 argument */
+ aaddi t0,t0,sizevmarg /* load address of next block */
+ aaddi t2,t2,8 /* increase stack position */
+ bnez t1,calljava_copyloop /* all arguments copied? */
+ nop
+
+calljava_nocopy:
+ ald itmp1,4*8(t4) /* pass method pointer via itmp1 */
ala mptr,asm_call_jit_compiler/* fake virtual function call (2 instr) */
- ast mptr,1*8(sp) /* store function address */
- move mptr,sp /* set method pointer */
+ ast mptr,2*8(t4) /* store function address */
+ ala mptr,1*8(t4) /* set method pointer */
- .set noreorder
-
ald pv,1*8(mptr) /* method call as in Java */
jalr pv /* call JIT compiler */
nop
- aaddiu pv,ra,-23*4 /* recompute procedure vector */
-#if 0
- move v0,zero /* clear return value (exception ptr) */
+L_asm_vm_call_method_recompute_pv:
+#if SIZEOF_VOID_P == 8
+ aaddiu pv,ra,-76*4 /* recompute procedure vector */
#else
- nop
+ aaddiu pv,ra,(asm_vm_call_method - L_asm_vm_call_method_recompute_pv)
#endif
-calljava_return:
+ .set reorder /* XXX we need to recompute pv */
- ld ra,0(sp) /* restore return address */
- ld pv,3*8(sp) /* restore procedure vector */
+ sll t1,s7,3 /* remove argument stackframe */
+ aaddu sp,sp,t1
- ldc1 fss0,4*8(sp) /* restore non JavaABI saved flt regs */
- ldc1 fss1,5*8(sp)
- ldc1 fss2,6*8(sp)
- ldc1 fss3,7*8(sp)
- ldc1 fss4,8*8(sp)
- ldc1 fss5,9*8(sp)
+calljava_return2:
+ ald ra,0*8(sp) /* restore return address */
+ ald pv,1*8(sp) /* restore procedure vector */
+ ald s7,3*8(sp)
+
+#if SIZEOF_VOID_P == 8
+ ldc1 fss0,5*8(sp) /* restore non JavaABI saved flt regs */
+ ldc1 fss1,6*8(sp)
+ ldc1 fss2,7*8(sp)
+ ldc1 fss3,8*8(sp)
+ ldc1 fss4,9*8(sp)
+ ldc1 fss5,10*8(sp)
+#endif
+
+ aaddiu sp,sp,12*8 /* free stack space */
j ra /* return */
- aaddiu sp,sp,10*8 /* free stack space */
- .set reorder
-
-calljava_xhandler:
+asm_vm_call_method_exception_handler:
+ sll t1,s7,3 /* remove stackframe */
+ aaddu sp,sp,t1
+#if SIZEOF_VOID_P == 4
+ aaddiu sp,sp,-4*4 /* reserve space for 1 argument */
+#endif
move a0,itmp1
jal builtin_throw_exception
- b calljava_return
-
- .end asm_calljavafunction_asm
-
+#if SIZEOF_VOID_P == 4
+ aaddiu sp,sp,4*4
#endif
+asm_vm_call_method_end:
+ b calljava_return2
+
+ .end asm_vm_call_method
/****************** function asm_call_jit_compiler *****************************
* *
*******************************************************************************/
-
.ent asm_call_jit_compiler
+
asm_call_jit_compiler:
+#if SIZEOF_VOID_P == 8
- lw t0,-12(ra) /* load instruction LD PV,xxx($y) */
- srl t0,t0,21 /* shift right register number $y */
- and t0,t0,31 /* isolate register number */
- addiu t0,t0,-mptrreg /* test for REG_METHODPTR */
- beqz t0,noregchange
-
- lw t0,0(ra) /* load instruction LDA PV,xxx(RA) */
- sll t0,t0,16
- sra t0,t0,16 /* isolate offset */
- aaddu mptr,t0,ra /* compute update address */
-
-noregchange:
-
- aaddiu sp,sp,-18*8 /* allocate stack space */
- sd a0,0*8(sp) /* save all argument registers */
- sd a1,1*8(sp) /* they could be used by method */
- sd a2,2*8(sp)
- sd a3,3*8(sp)
- sd a4,4*8(sp)
- sd a5,5*8(sp)
- sd a6,6*8(sp)
- sd a7,7*8(sp)
- sdc1 fa0,8*8(sp)
- sdc1 fa1,9*8(sp)
- sdc1 fa2,10*8(sp)
- sdc1 fa3,11*8(sp)
- sdc1 fa4,12*8(sp)
- sdc1 fa5,13*8(sp)
- sdc1 fa6,14*8(sp)
- sdc1 fa7,15*8(sp)
- sd mptr,16*8(sp) /* save method pointer */
- sd ra,17*8(sp) /* save return address */
-
- ald a0,0(itmp1) /* pass 'methodinfo' pointer to */
- jal jit_compile /* jit compiler */
-
- ld a0,0*8(sp) /* restore argument registers */
- ld a1,1*8(sp) /* they could be used by method */
- ld a2,2*8(sp)
- ld a3,3*8(sp)
- ld a4,4*8(sp)
- ld a5,5*8(sp)
- ld a6,6*8(sp)
- ld a7,7*8(sp)
- ldc1 fa0,8*8(sp)
- ldc1 fa1,9*8(sp)
- ldc1 fa2,10*8(sp)
- ldc1 fa3,11*8(sp)
- ldc1 fa4,12*8(sp)
- ldc1 fa5,13*8(sp)
- ldc1 fa6,14*8(sp)
- ldc1 fa7,15*8(sp)
- ld mptr,16*8(sp) /* restore method pointer */
- ld ra,17*8(sp) /* restore return address */
- aaddiu sp,sp,18*8 /* deallocate stack area */
-
- lw t0,-12(ra) /* load instruction LDQ PV,xxx($yy) */
- sll t0,t0,16
- sra t0,t0,16 /* isolate offset */
-
- aaddu t0,t0,mptr /* compute update address via method pointer*/
- ast v0,0(t0) /* save new method address there */
-
- move pv,v0 /* move method address into pv */
+ aaddiu sp,sp,-(ARG_CNT+2)*8 /* +2: keep stack 16-bytes aligned */
- jr pv /* and call method. The method returns */
- /* directly to the caller (ra). */
+ ast ra,0*8(sp) /* save return address */
- .end asm_call_jit_compiler
+ SAVE_ARGUMENT_REGISTERS(1)
+ move a0,itmp1 /* pass methodinfo pointer */
+ move a1,mptr /* pass method pointer */
+ aaddiu a2,sp,(ARG_CNT+2)*8 /* pass java sp */
+ move a3,ra
+ jal jit_asm_compile /* call jit compiler */
+ move pv,v0
-/****************** function asm_dumpregistersandcall **************************
-* *
-* This funtion saves all callee saved (address) 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); *
-* *
-*******************************************************************************/
+ ald ra,0*8(sp) /* restore return address */
- .ent asm_dumpregistersandcall
-asm_dumpregistersandcall:
- aaddiu sp,sp,-10*8 /* allocate stack */
- sd ra,0(sp) /* save return address */
+ RESTORE_ARGUMENT_REGISTERS(1)
- sd s0,1*8(sp) /* save all callee saved registers */
- sd s1,2*8(sp)
- sd s2,3*8(sp)
- sd s3,4*8(sp)
- sd s4,5*8(sp)
- sd s5,6*8(sp)
- sd s6,7*8(sp)
- sd s7,8*8(sp)
- sd s8,9*8(sp)
+ aaddiu sp,sp,(ARG_CNT+2)*8 /* remove stack frame */
- move itmp3,a0
- jalr itmp3 /* and call function */
+#else /* SIZEOF_VOID_P == 8 */
- ld ra,0(sp) /* restore return address */
- aaddiu sp,sp,10*8 /* deallocate stack */
- j ra /* return */
+ aaddiu sp,sp,-(ARG_CNT+2)*8 /* +4: keep stack 16-bytes aligned */
- .end asm_dumpregistersandcall
+ ast ra,4*4+0*4(sp) /* save return address */
+ SAVE_ARGUMENT_REGISTERS(6)
+
+ move a0,itmp1 /* pass methodinfo pointer */
+ move a1,mptr /* pass method pointer */
+ aaddiu a2,sp,(ARG_CNT+2)*8 /* pass java sp */
+ move a3,ra
+ jal jit_asm_compile /* call jit compiler */
+ move pv,v0
+
+ ald ra,4*4+0*4(sp) /* restore return address */
+
+ RESTORE_ARGUMENT_REGISTERS(6)
+
+ aaddiu sp,sp,(ARG_CNT+2)*8 /* remove stack frame */
+
+#endif /* SIZEOF_VOID_P == 8 */
+
+ beqz pv,L_asm_call_jit_compiler_exception
+
+ jr pv /* and call method. The method returns */
+ /* directly to the caller (ra). */
+
+L_asm_call_jit_compiler_exception:
+ aaddiu sp,sp,-2*8
+ ast ra,0*8(sp)
+ jal exceptions_get_and_clear_exception
+ ald ra,0*8(sp)
+ aaddiu sp,sp,2*8
+
+ move xptr,v0 /* get exception */
+ aaddiu xpc,ra,-4 /* exception address is RA - 4 */
+ b asm_handle_nat_exception
+
+ .end asm_call_jit_compiler
+
+
+/* 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.
-/********************* 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); *
-* *
*******************************************************************************/
.ent asm_handle_nat_exception
+
asm_handle_nat_exception:
+L_asm_handle_exception_stack_loop:
+#if SIZEOF_VOID_P == 8
+ aaddiu sp,sp,-6*8 /* keep stack 16-byte aligned */
+ ast xptr,0*8(sp) /* save exception pointer */
+ ast xpc,1*8(sp) /* save exception pc */
+ ast ra,3*8(sp) /* save RA */
+ ast zero,4*8(sp) /* save maybe-leaf flag (cleared) */
+#else
+ aaddiu sp,sp,-(4*4+6*8) /* allocate stack */
+ ast xptr,4*4+0*8(sp) /* save exception pointer */
+ ast xpc,4*4+1*8(sp) /* save exception pc */
+ ast ra,4*4+3*8(sp) /* save return address */
+ ast zero,4*4+4*8(sp) /* save maybe-leaf flag (cleared) */
+#endif
+
+ move a0,ra /* pass RA */
+ jal md_codegen_get_pv_from_pc /* get PV from RA */
- lw t0,0(ra) /* load instruction LDA PV,xxx(RA) */
- sll t0,t0,16
- sra t0,t0,16 /* isolate offset */
- aaddu pv,t0,ra /* compute update address */
+#if SIZEOF_VOID_P == 8
+ ast v0,2*8(sp) /* save PV */
+
+ ald a0,0*8(sp) /* pass xptr */
+ ald a1,1*8(sp) /* pass xpc */
+ move a2,v0 /* pass PV */
+ aaddiu a3,sp,6*8 /* pass Java SP */
+#else
+ ast v0,4*4+2*8(sp) /* save data segment pointer */
+
+ ald a0,4*4+0*8(sp) /* pass exception pointer */
+ ald a1,4*4+1*8(sp) /* pass exception pc */
+ move a2,v0 /* pass data segment pointer */
+ aaddiu a3,sp,(4*4+6*8) /* pass Java stack pointer */
+#endif
+
+ b L_asm_handle_exception_continue
.aent asm_handle_exception
+
asm_handle_exception:
+ aaddiu sp,sp,-(ARG_CNT+TMP_CNT)*8 /* 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 */
+
+#if SIZEOF_VOID_P == 8
+ aaddiu sp,sp,-6*8 /* allocate stack */
+ ast xptr,0*8(sp) /* save exception pointer */
+ ast pv,2*8(sp) /* save PV */
+ ast ra,3*8(sp) /* save RA */
+ addu t0,zero,1 /* set maybe-leaf flag */
+ ast t0,4*8(sp) /* save maybe-leaf flag */
+#else
+ aaddiu sp,sp,-(4*4+6*8) /* allocate stack */
+ ast xptr,4*4+0*8(sp) /* save exception pointer */
+ ast xpc,4*4+1*8(sp) /* save exception pc */
+ ast pv,4*4+2*8(sp) /* save data segment pointer */
+ ast ra,4*4+3*8(sp) /* save return address */
+ addu t0,zero,1 /* set maybe-leaf flag */
+ ast t0,4*4+4*8(sp) /* save maybe-leaf flag */
+#endif
+
+ move a0,xptr /* pass xptr */
+ move a1,xpc /* pass xpc */
+ move a2,pv /* pass PV */
- aaddiu sp,sp,-14*8 /* allocate stack */
- sd v0,0*8(sp) /* save possible used registers */
- sd t0,1*8(sp) /* also registers used by trace_exception */
- sd t1,2*8(sp)
- sd t2,3*8(sp)
- sd t3,4*8(sp)
- sd t4,5*8(sp)
- sd a0,6*8(sp)
- sd a1,7*8(sp)
- sd a2,8*8(sp)
- sd a3,9*8(sp)
- sd a4,10*8(sp)
- sd a5,11*8(sp)
- sd a6,12*8(sp)
- sd a7,13*8(sp)
-
- addu t3,zero,1 /* set no unwind flag */
-ex_stack_loop:
- aaddiu sp,sp,-6*8 /* allocate stack */
- sd xptr,0*8(sp) /* save used registers */
- sd xpc,1*8(sp)
- sd pv,2*8(sp)
- sd ra,3*8(sp)
- sd t3,4*8(sp)
-
- move a0,xptr
- ald a1,MethodPointer(pv)
- move a2,xpc
- move a3,t3
- jal builtin_trace_exception /* trace_exception(xptr,methodptr) */
+#if SIZEOF_VOID_P == 8
+ aaddiu a3,sp,(ARG_CNT+TMP_CNT+6)*8 /* pass Java SP */
+#else
+ aaddiu a3,sp,4*4+(ARG_CNT+TMP_CNT+6)*8 /* pass Java stack pointer */
+#endif
+
+L_asm_handle_exception_continue:
+ jal exceptions_handle_exception
- ld xptr,0*8(sp) /* restore used register */
- ld xpc,1*8(sp)
- ld pv,2*8(sp)
- ld ra,3*8(sp)
- ld t3,4*8(sp)
- aaddiu sp,sp,6*8 /* deallocate stack */
+ beqz v0,L_asm_handle_exception_not_catched
+
+ move xpc,v0 /* move handlerpc into xpc */
+
+#if SIZEOF_VOID_P == 8
+ ald xptr,0*8(sp) /* restore exception pointer */
+ ald pv,2*8(sp) /* restore PV */
+ ald ra,3*8(sp) /* restore RA */
+ ald t0,4*8(sp) /* get maybe-leaf flag */
+ aaddiu sp,sp,6*8 /* free stackframe */
+#else
+ ald xptr,4*4+0*8(sp) /* restore exception pointer */
+ ald pv,4*4+2*8(sp) /* restore data segment pointer */
+ ald ra,4*4+3*8(sp) /* restore return address */
+ ald t0,4*4+4*8(sp) /* get maybe-leaf flag */
+ aaddiu sp,sp,4*4+6*8 /* free stackframe */
+#endif
- lw t0,ExTableSize(pv) /* t0 = exception table size */
- beqz t0,empty_table /* if empty table skip */
- aaddiu t1,pv,ExTableStart /* t1 = start of exception table */
-
-ex_table_loop:
- ald t2,ExStartPC(t1) /* t2 = exception start pc */
- slt t2,xpc,t2 /* t2 = (xpc < startpc) */
- bnez t2,ex_table_cont /* if (true) continue */
- ald t2,ExEndPC(t1) /* t2 = exception end pc */
- slt t2,xpc,t2 /* t2 = (xpc < endpc) */
- beqz t2,ex_table_cont /* if (false) continue */
- ald a1,ExCatchType(t1) /* arg1 = exception catch type */
- beqz a1,ex_handle_it /* NULL catches everything */
-
- ald a0,offobjvftbl(xptr) /* a0 = vftblptr(xptr) */
- ald a1,offobjvftbl(a1) /* a1 = vftblptr(catchtype) class (not obj) */
- lw a0,offbaseval(a0) /* a0 = baseval(xptr) */
- lw v0,offbaseval(a1) /* a2 = baseval(catchtype) */
- lw a1,offdiffval(a1) /* a1 = diffval(catchtype) */
- subu a0,a0,v0 /* a0 = baseval(xptr) - baseval(catchtype) */
- sltu v0,a1,a0 /* v0 = xptr is instanceof catchtype */
- bnez v0,ex_table_cont /* if (false) continue */
-
-ex_handle_it:
-
- ald xpc,ExHandlerPC(t1) /* xpc = exception handler pc */
-
- beqz t3,ex_jump /* if (!(no stack unwinding) skip */
-
- ld v0,0*8(sp) /* restore possible used registers */
- ld t0,1*8(sp) /* also registers used by trace_exception */
- ld t1,2*8(sp)
- ld t2,3*8(sp)
- ld t3,4*8(sp)
- ld t4,5*8(sp)
- ld a0,6*8(sp)
- ld a1,7*8(sp)
- ld a2,8*8(sp)
- ld a3,9*8(sp)
- ld a4,10*8(sp)
- ld a5,11*8(sp)
- ld a6,12*8(sp)
- ld a7,13*8(sp)
+ beqz t0,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 */
- aaddiu sp,sp,14*8 /* deallocate stack */
-
-ex_jump:
- jr xpc /* jump to the handler */
-
-ex_table_cont:
- aaddiu t1,t1,ExEntrySize /* next exception table entry */
- addiu t0,t0,-1 /* decrement entry counter */
- bgtz t0,ex_table_loop /* if (t0 > 0) next entry */
-
-empty_table:
- beqz t3,ex_already_cleared /* if here the first time, then */
- aaddiu sp,sp,14*8 /* deallocate stack and */
- move t3,zero /* clear the no unwind flag */
-ex_already_cleared:
- lw t0,IsSync(pv) /* t0 = SyncOffset */
- beqz t0,no_monitor_exit /* if zero no monitorexit */
- aaddu t0,sp,t0 /* add stackptr to Offset */
- ald a0,-8(t0) /* load monitorexit pointer */
-
- aaddiu sp,sp,-8*8 /* allocate stack */
- sd t0,0*8(sp) /* save used register */
- sd t1,1*8(sp)
- sd t3,2*8(sp)
- sd xptr,3*8(sp)
- sd xpc,4*8(sp)
- sd pv,5*8(sp)
- sd ra,6*8(sp)
-
- jal builtin_monitorexit /* builtin_monitorexit(objectptr) */
+ aaddiu sp,sp,(ARG_CNT+TMP_CNT)*8 /* remove maybe-leaf stackframe */
+
+L_asm_handle_exception_no_leaf:
+ jr xpc /* jump to the handler */
+
+L_asm_handle_exception_not_catched:
+#if SIZEOF_VOID_P == 8
+ ald xptr,0*8(sp) /* restore xptr */
+ ald pv,2*8(sp) /* restore PV */
+ ald ra,3*8(sp) /* restore RA */
+ ald t0,4*8(sp) /* get maybe-leaf flag */
+ aaddiu sp,sp,6*8 /* free stackframe */
+#else
+ ald xptr,4*4+0*8(sp) /* restore xptr */
+ ald pv,4*4+2*8(sp) /* restore PV */
+ ald ra,4*4+3*8(sp) /* restore RA */
+ ald t0,4*4+4*8(sp) /* get maybe-leaf flag */
+ aaddiu sp,sp,4*4+6*8 /* free stackframe */
+#endif
- ld t0,0*8(sp) /* restore used register */
- ld t1,1*8(sp)
- ld t3,2*8(sp)
- ld xptr,3*8(sp)
- ld xpc,4*8(sp)
- ld pv,5*8(sp)
- ld ra,6*8(sp)
- aaddiu sp,sp,8*8 /* deallocate stack */
-
-no_monitor_exit:
- lw t0,FrameSize(pv) /* t0 = frame size */
- aaddu sp,sp,t0 /* unwind stack */
- move t0,sp /* t0 = pointer to save area */
- lw t1,IsLeaf(pv) /* t1 = is leaf procedure */
- bnez t1,ex_no_restore /* if (leaf) skip */
- ld ra,-8(t0) /* restore ra */
- aaddiu t0,t0,-8 /* t0-- */
-ex_no_restore:
- move xpc,ra /* the new xpc is ra */
- lw t1,IntSave(pv) /* t1 = saved int register count */
- ala t2,ex_int2 /* t2 = current pc */
- sll t1,t1,2 /* t1 = register count * 4 */
- asubu t2,t2,t1 /* t2 = ex_int_sav - 4 * register count */
- jr t2 /* jump to save position */
- ld s0,-8*8(t0)
- ld s1,-7*8(t0)
- ld s2,-6*8(t0)
- ld s3,-5*8(t0)
- ld s4,-4*8(t0)
- ld s5,-3*8(t0)
- ld s6,-2*8(t0)
- ld s7,-1*8(t0)
+ beqz t0,L_asm_handle_exception_no_leaf_stack
+
+ aaddiu sp,sp,(ARG_CNT+TMP_CNT)*8 /* remove maybe-leaf stackframe */
+ move t0,zero /* clear the maybe-leaf flag */
+
+L_asm_handle_exception_no_leaf_stack:
+ lw t1,FrameSize(pv) /* get frame size */
+ aaddu t1,sp,t1 /* pointer to save area */
+
+ lw t2,IsLeaf(pv) /* is leaf procedure */
+ bnez t2,L_asm_handle_exception_no_ra_restore
+
+ ald ra,-1*8(t1) /* restore ra */
+ aaddiu t1,t1,-8 /* t1-- */
+
+L_asm_handle_exception_no_ra_restore:
+ move xpc,ra /* the new xpc is ra */
+ lw t2,IntSave(pv) /* t1 = saved int register count */
+ ala t3,ex_int2 /* t3 = current pc */
+ sll t2,t2,2 /* t2 = register count * 4 */
+ asubu t3,t3,t2 /* t3 = IntSave - 4 * register count */
+ jr t3 /* jump to save position */
+
+ ald s0,-8*8(t1)
+ ald s1,-7*8(t1)
+ ald s2,-6*8(t1)
+ ald s3,-5*8(t1)
+ ald s4,-4*8(t1)
+ ald s5,-3*8(t1)
+ ald s6,-2*8(t1)
+ ald s7,-1*8(t1)
+
ex_int2:
- sll t1,t1,1 /* t1 = register count * 4 * 2 */
- asubu t0,t0,t1 /* t0 = t0 - 8 * register count */
-
- lw t1,FltSave(pv) /* t1 = saved flt register count */
- ala t2,ex_flt2 /* t2 = current pc */
- sll t1,t1,2 /* t1 = register count * 4 */
- asubu t2,t2,t1 /* t2 = ex_int_sav - 4 * register count */
- jr t2 /* jump to save position */
- ldc1 fs0,-4*8(t0)
- ldc1 fs1,-3*8(t0)
- ldc1 fs2,-2*8(t0)
- ldc1 fs3,-1*8(t0)
+ sll t2,t2,1 /* t2 = register count * 4 * 2 */
+ asubu t1,t1,t2 /* t1 = t0 - 8 * register count */
+
+ lw t2,FltSave(pv) /* t2 = saved flt register count */
+ ala t3,ex_flt2 /* t3 = current pc */
+ sll t2,t2,2 /* t2 = register count * 4 */
+ asubu t3,t3,t2 /* t3 = ex_int_sav - 4 * register count */
+ jr t3 /* jump to save position */
+
+#if SIZEOF_VOID_P == 8
+ ldc1 fs0,-4*8(t1)
+ ldc1 fs1,-3*8(t1)
+ ldc1 fs2,-2*8(t1)
+ ldc1 fs3,-1*8(t1)
+#else /* SIZEOF_VOID_P == 8 */
+# if !defined(ENABLE_SOFT_FLOAT)
+ ldc1 fs0,-4*8(t1)
+ ldc1 fs1,-3*8(t1)
+ ldc1 fs2,-2*8(t1)
+ ldc1 fs3,-1*8(t1)
+ ldc1 fs4,-1*8(t1)
+ ldc1 fs5,-1*8(t1)
+# endif /* !defined(ENABLE_SOFT_FLOAT) */
+#endif /* SIZEOF_VOID_P == 8 */
+
ex_flt2:
- lw t0,0(ra) /* load instruction LDA PV,xxx(RA) */
- sll t0,t0,16
- sra t0,t0,16 /* isolate offset */
- aaddu pv,t0,ra /* compute update address */
- b ex_stack_loop
+ lw t1,FrameSize(pv) /* get frame size */
+ aaddu sp,sp,t1 /* unwind stack */
+ b L_asm_handle_exception_stack_loop
.end asm_handle_nat_exception
-/********************* function asm_builtin_monitorenter ***********************
-* *
-* Does null check and calls monitorenter or throws an exception *
-* *
+/* asm_abstractmethoderror *****************************************************
+
+ Creates and throws an AbstractMethodError.
+
*******************************************************************************/
- .ent asm_builtin_monitorenter
-asm_builtin_monitorenter:
+ .ent asm_abstractmethoderror
- beqz a0,nb_monitorenter /* if (null) throw exception */
- ala t9,builtin_monitorenter /* else call builtin_monitorenter */
- j t9
+asm_abstractmethoderror:
+ aaddiu sp,sp,-2*8 /* create stackframe */
+ ast ra,0*8(sp) /* save return address */
+ aaddiu a0,sp,2*8 /* pass java sp */
+ move a1,ra /* pass exception address */
+ jal exceptions_asm_new_abstractmethoderror
+ ald ra,0*8(sp) /* restore return address */
+ aaddiu sp,sp,2*8 /* remove stackframe */
-nb_monitorenter:
- ald xptr,proto_java_lang_NullPointerException
- aaddiu xpc,ra,-4 /* faulting address is return adress - 4*/
+ move xptr,v0 /* get exception pointer */
+ aaddiu xpc,ra,-4 /* exception address is ra - 4 */
b asm_handle_nat_exception
- .end asm_builtin_monitorenter
+ .end asm_abstractmethoderror
-/********************* function asm_builtin_monitorexit ************************
-* *
-* Does null check and calls monitorexit or throws an exception *
-* *
-*******************************************************************************/
-
- .ent asm_builtin_monitorexit
-asm_builtin_monitorexit:
- beqz a0,nb_monitorexit /* if (null) throw exception */
- ala t9,builtin_monitorexit /* else call builtin_monitorexit */
- j t9
+/* asm_patcher_wrapper *********************************************************
-nb_monitorexit:
- ald xptr,proto_java_lang_NullPointerException
- aaddiu xpc,ra,-4 /* faulting address is return adress - 4*/
- b asm_handle_nat_exception
- .end asm_builtin_monitorexit
+ XXX
+ Stack layout:
+ 56 return address into JIT code (patch position)
+ 48 pointer to virtual java_objectheader
+ 40 machine code (which is patched back later)
+ 32 machine code (which is patched back later)
+ 24 machine code (which is patched back later)
+ 16 unresolved class/method/field reference
+ 8 data segment displacement from load instructions
+ 0 patcher function pointer to call
-/************************ function asm_builtin_idiv ****************************
-* *
-* Does null check and calls idiv or throws an exception *
-* *
*******************************************************************************/
+
+ .ent asm_patcher_wrapper
- .ent asm_builtin_idiv
-asm_builtin_idiv:
+asm_patcher_wrapper:
+#if SIZEOF_VOID_P == 8
- beqz a1,nb_idiv /* if (null) throw exception */
- ala itmp3,builtin_idiv /* else call builtin_idiv */
- j itmp3
+ aaddiu sp,sp,-((2+16+22+4)*8)/* create stack frame */
-nb_idiv:
- ald xptr,proto_java_lang_ArithmeticException
- aaddiu xpc,ra,-4 /* faulting address is return adress - 4*/
- b asm_handle_nat_exception
- .end asm_builtin_idiv
+ SAVE_RETURN_REGISTERS(0) /* save 1 int/1 float return registers */
+ SAVE_ARGUMENT_REGISTERS(2) /* save 8 int/8 float argument registers */
+ SAVE_TEMPORARY_REGISTERS(18) /* save 5 int/16 float temporary registers */
+ ast itmp1,(2+16+22+0)*8(sp) /* save itmp1 */
+ ast itmp2,(2+16+22+1)*8(sp) /* save itmp2 */
+ ast ra,(2+16+22+2)*8(sp) /* save method return address (for leafs) */
+ ast pv,(2+16+22+3)*8(sp) /* save pv of calling java function */
-/************************ function asm_builtin_ldiv ****************************
-* *
-* Does null check and calls ldiv or throws an exception *
-* *
-*******************************************************************************/
+ aaddiu a0,sp,(2+16+22+4)*8 /* pass SP of patcher stub */
+ move a1,pv /* pass PV */
+ move a2,ra /* pass RA (correct for leafs) */
+ jal patcher_wrapper
+ move itmp3,v0
- .ent asm_builtin_ldiv
-asm_builtin_ldiv:
+ RESTORE_RETURN_REGISTERS(0) /* restore 1 int/1 float return registers */
+ RESTORE_ARGUMENT_REGISTERS(2) /* restore 8 int/8 float argument registers */
+ RESTORE_TEMPORARY_REGISTERS(18) /* restore 5 int/16 float temporary reg. */
- beqz a1,nb_ldiv /* if (null) throw exception */
- ala itmp3,builtin_ldiv /* else call builtin_ldiv */
- j itmp3
+ ald itmp1,(2+16+22+0)*8(sp) /* restore itmp1 */
+ ald itmp2,(2+16+22+1)*8(sp) /* restore itmp2 */
+ ald ra,(2+16+22+2)*8(sp) /* restore method return address (for leafs)*/
+ ald pv,(2+16+22+3)*8(sp) /* restore pv of calling java function */
-nb_ldiv:
- ald xptr,proto_java_lang_ArithmeticException
- aaddiu xpc,ra,-4 /* faulting address is return adress - 4*/
- b asm_handle_nat_exception
- .end asm_builtin_ldiv
+ bnez itmp3,L_asm_patcher_wrapper_exception
+ ald itmp3,(7+2+16+22+4)*8(sp) /* load RA */
+ aaddiu sp,sp,(8+2+16+22+4)*8 /* remove stack frame */
-/************************ function asm_builtin_irem ****************************
-* *
-* Does null check and calls irem or throws an exception *
-* *
-*******************************************************************************/
+ jr itmp3 /* jump to new patched code */
- .ent asm_builtin_irem
-asm_builtin_irem:
+L_asm_patcher_wrapper_exception:
+ move xptr,itmp3 /* get exception */
+ ald xpc,(7+2+16+22+4)*8(sp) /* xpc is RA */
+ aaddiu sp,sp,(8+2+16+22+4)*8 /* remove stack frame */
- beqz a1,nb_irem /* if (null) throw exception */
- ala t9,builtin_irem /* else call builtin_irem */
- j t9
+#else /* SIZEOF_VOID_P == 8 */
-nb_irem:
- ald xptr,proto_java_lang_ArithmeticException
- aaddiu xpc,ra,-4 /* faulting address is return adress - 4*/
- b asm_handle_nat_exception
- .end asm_builtin_irem
+ aaddiu sp,sp,-((6+4+8+16+7)*4) /* create stack frame */
+ /* +7 keeps the SP 16-bytes aligned */
+ SAVE_RETURN_REGISTERS(6) /* save 2 int / 1 float return registers */
+ SAVE_ARGUMENT_REGISTERS(10) /* save 4 int / 2 float argument registers */
+ SAVE_TEMPORARY_REGISTERS(18) /* save 8 int / 4 float temporary registers */
-/************************ function asm_builtin_lrem ****************************
-* *
-* Does null check and calls lrem or throws an exception *
-* *
-*******************************************************************************/
+ ast itmp1,(6+4+8+16+0)*4(sp) /* save itmp1 */
+ ast itmp2,(6+4+8+16+1)*4(sp) /* save itmp2 */
+ ast ra,(6+4+8+16+2)*4(sp) /* save method return address (for leafs) */
+ ast pv,(6+4+8+16+3)*4(sp) /* save pv of calling java function */
- .ent asm_builtin_lrem
-asm_builtin_lrem:
+ aaddiu a0,sp,(6+4+8+16+7)*4 /* pass SP of patcher stub */
+ move a1,pv /* pass PV */
+ move a2,ra /* pass RA (correct for leafs) */
+ jal patcher_wrapper
+ move itmp3,v0
- beqz a1,nb_lrem /* if (null) throw exception */
- ala t9,builtin_lrem /* else call builtin_lrem */
- j t9
+ RESTORE_RETURN_REGISTERS(6) /* restore 2 int / 2 float return registers */
+ RESTORE_ARGUMENT_REGISTERS(10) /* restore 4 int / 2 float argument regs */
+ RESTORE_TEMPORARY_REGISTERS(18) /* restore 8 int / 4 float temporary regs */
-nb_lrem:
- ald xptr,proto_java_lang_ArithmeticException
- aaddiu xpc,ra,-4 /* faulting address is return adress - 4*/
- b asm_handle_nat_exception
- .end asm_builtin_lrem
+ ald itmp1,(6+4+8+16+0)*4(sp) /* restore itmp1 */
+ ald itmp2,(6+4+8+16+1)*4(sp) /* restore itmp2 */
+ ald ra,(6+4+8+16+2)*4(sp) /* restore method return address (for leafs)*/
+ ald pv,(6+4+8+16+3)*4(sp) /* restore pv of calling java function */
+ bnez itmp3,L_asm_wrapper_patcher_exception
-/******************* function asm_builtin_checkarraycast ***********************
-* *
-* Does the cast check and eventually throws an exception *
-* *
-*******************************************************************************/
+ ald itmp3,7*8+(6+4+8+16+7)*4(sp) /* load RA */
+ aaddiu sp,sp,8*8+(6+4+8+16+7)*4 /* remove stack frame */
- .ent asm_builtin_checkarraycast
-asm_builtin_checkarraycast:
-
- aaddiu sp,sp,-16 /* allocate stack space */
- sd ra,0(sp) /* save return address */
- sd a0,8(sp) /* save object pointer */
- jal builtin_checkarraycast /* builtin_checkarraycast */
- beqz v0,nb_carray_throw /* if (false) throw exception */
- ld ra,0(sp) /* restore return address */
- ld v0,8(sp) /* return object pointer */
- aaddiu sp,sp,16 /* deallocate stack */
- j ra /* return */
+ jr itmp3 /* jump to new patched code */
-nb_carray_throw:
- ald xptr,proto_java_lang_ClassCastException
- ld ra,0(sp) /* restore return address */
- aaddiu sp,sp,16 /* free stack space */
- aaddiu xpc,ra,-4 /* faulting address is return adress - 4*/
- b asm_handle_nat_exception
- .end asm_builtin_checkarraycast
+L_asm_wrapper_patcher_exception:
+ move xptr,itmp3 /* get exception */
+ ald xpc,7*8+(6+4+8+16+7)*4(sp) /* xpc is RA */
+ aaddiu sp,sp,8*8+(6+4+8+16+7)*4 /* remove stack frame */
+#endif /* SIZEOF_VOID_P == 8 */
-/********************* function asm_builtin_checkcast **************************
-* *
-* Does the cast check and eventually throws an exception *
-* *
-*******************************************************************************/
+ b asm_handle_exception
- .ent asm_builtin_checkcast
-asm_builtin_checkcast:
-
- aaddiu sp,sp,-16 /* allocate stack space */
- sd ra,0(sp) /* save return address */
- sd a0,8(sp) /* save object pointer */
- jal builtin_checkcast /* builtin_checkcast */
- beqz v0,nb_ccast_throw /* if (false) throw exception */
- ld ra,0(sp) /* restore return address */
- ld v0,8(sp) /* return object pointer */
- aaddiu sp,sp,16 /* deallocate stack */
- j ra /* return */
+ .end asm_patcher_wrapper
-nb_ccast_throw:
- ald xptr,proto_java_lang_ClassCastException
- ld ra,0(sp) /* restore return address */
- aaddiu sp,sp,16 /* free stack space */
- aaddiu xpc,ra,-4 /* faulting address is return adress - 4*/
- b asm_handle_nat_exception
- .end asm_builtin_checkcast
+#if defined(ENABLE_REPLACEMENT)
+
+/* 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:
+ 16 start of stack inside method to replace
+ 0 rplpoint * info on the replacement point that was reached
+
+ NOTE: itmp3 has been clobbered by the replacement-out stub!
-/******************* function asm_builtin_aastore ******************************
-* *
-* Does the cast check and eventually throws an exception *
-* a0 = arrayref, a1 = index, a2 = value *
-* *
*******************************************************************************/
- .ent asm_builtin_aastore
-asm_builtin_aastore:
-
- beqz a0,nb_aastore_null /* if null pointer throw exception */
- lw t0,offarraysize(a0) /* load size */
- aaddiu sp,sp,-32 /* allocate stack space */
- sd ra,0(sp) /* save return address */
- asll t1,a1,ashift /* add index*8 to arrayref */
- aaddu t1,a0,t1 /* add index * ashift to arrayref */
- sltu t0,a1,t0 /* do bound check */
- beqz t0,nb_aastore_bound /* if out of bounds throw exception */
- move a1,a2 /* object is second argument */
- sd t1,8(sp) /* save store position */
- sd a1,16(sp) /* save object */
- jal builtin_canstore /* builtin_canstore(arrayref,object) */
- ld ra,0(sp) /* restore return address */
- ld a0,8(sp) /* restore store position */
- ld a1,16(sp) /* restore object */
- aaddiu sp,sp,32 /* free stack space */
- beqz v0,nb_aastore_throw /* if (false) throw exception */
- ast a1,offobjarrdata(a0) /* store objectptr in array */
- j ra /* return */
+/* some room to accomodate changes of the stack frame size during replacement */
+ /* XXX we should find a cleaner solution here */
+#define REPLACEMENT_ROOM 512
+
+#define REPLACEMENT_STACK_OFFSET ((sizeexecutionstate + REPLACEMENT_ROOM + 0xf) & ~0xf)
+
+ .ent asm_replacement_out
+
+asm_replacement_out:
+ /* create stack frame */
+ aaddiu sp,sp,-REPLACEMENT_STACK_OFFSET
+
+ /* save registers in execution state */
+ ast $0 ,( 0*8+offes_intregs)(sp)
+ ast $1 ,( 1*8+offes_intregs)(sp)
+ ast $2 ,( 2*8+offes_intregs)(sp)
+ ast $3 ,( 3*8+offes_intregs)(sp)
+ ast $4 ,( 4*8+offes_intregs)(sp)
+ ast $5 ,( 5*8+offes_intregs)(sp)
+ ast $6 ,( 6*8+offes_intregs)(sp)
+ ast $7 ,( 7*8+offes_intregs)(sp)
+ ast $8 ,( 8*8+offes_intregs)(sp)
+ ast $9 ,( 9*8+offes_intregs)(sp)
+ ast $10,(10*8+offes_intregs)(sp)
+ ast $11,(11*8+offes_intregs)(sp)
+ ast $12,(12*8+offes_intregs)(sp)
+ ast $13,(13*8+offes_intregs)(sp)
+ ast $14,(14*8+offes_intregs)(sp)
+ ast $15,(15*8+offes_intregs)(sp)
+ ast $16,(16*8+offes_intregs)(sp)
+ ast $17,(17*8+offes_intregs)(sp)
+ ast $18,(18*8+offes_intregs)(sp)
+ ast $19,(19*8+offes_intregs)(sp)
+ ast $20,(20*8+offes_intregs)(sp)
+ ast $21,(21*8+offes_intregs)(sp)
+ ast $22,(22*8+offes_intregs)(sp)
+ ast $23,(23*8+offes_intregs)(sp)
+ ast $24,(24*8+offes_intregs)(sp)
+ ast $25,(25*8+offes_intregs)(sp)
+ ast $26,(26*8+offes_intregs)(sp)
+ ast $27,(27*8+offes_intregs)(sp)
+ ast $28,(28*8+offes_intregs)(sp)
+ ast $29,(29*8+offes_intregs)(sp)
+ ast $30,(30*8+offes_intregs)(sp)
+ ast $31,(31*8+offes_intregs)(sp)
+
+#if SIZEOF_VOID_P == 8
+
+ sdc1 $f0 ,( 0*8+offes_fltregs)(sp)
+ sdc1 $f1 ,( 1*8+offes_fltregs)(sp)
+ sdc1 $f2 ,( 2*8+offes_fltregs)(sp)
+ sdc1 $f3 ,( 3*8+offes_fltregs)(sp)
+ sdc1 $f4 ,( 4*8+offes_fltregs)(sp)
+ sdc1 $f5 ,( 5*8+offes_fltregs)(sp)
+ sdc1 $f6 ,( 6*8+offes_fltregs)(sp)
+ sdc1 $f7 ,( 7*8+offes_fltregs)(sp)
+ sdc1 $f8 ,( 8*8+offes_fltregs)(sp)
+ sdc1 $f9 ,( 9*8+offes_fltregs)(sp)
+ sdc1 $f10,(10*8+offes_fltregs)(sp)
+ sdc1 $f11,(11*8+offes_fltregs)(sp)
+ sdc1 $f12,(12*8+offes_fltregs)(sp)
+ sdc1 $f13,(13*8+offes_fltregs)(sp)
+ sdc1 $f14,(14*8+offes_fltregs)(sp)
+ sdc1 $f15,(15*8+offes_fltregs)(sp)
+ sdc1 $f16,(16*8+offes_fltregs)(sp)
+ sdc1 $f17,(17*8+offes_fltregs)(sp)
+ sdc1 $f18,(18*8+offes_fltregs)(sp)
+ sdc1 $f19,(19*8+offes_fltregs)(sp)
+ sdc1 $f20,(20*8+offes_fltregs)(sp)
+ sdc1 $f21,(21*8+offes_fltregs)(sp)
+ sdc1 $f22,(22*8+offes_fltregs)(sp)
+ sdc1 $f23,(23*8+offes_fltregs)(sp)
+ sdc1 $f24,(24*8+offes_fltregs)(sp)
+ sdc1 $f25,(25*8+offes_fltregs)(sp)
+ sdc1 $f26,(26*8+offes_fltregs)(sp)
+ sdc1 $f27,(27*8+offes_fltregs)(sp)
+ sdc1 $f28,(28*8+offes_fltregs)(sp)
+ sdc1 $f29,(29*8+offes_fltregs)(sp)
+ sdc1 $f30,(30*8+offes_fltregs)(sp)
+ sdc1 $f31,(31*8+offes_fltregs)(sp)
+
+#else /* SIZEOF_VOID_P == 8 */
+
+ sdc1 $f0 ,( 0*8+offes_fltregs)(sp)
+ sdc1 $f2 ,( 2*8+offes_fltregs)(sp)
+ sdc1 $f4 ,( 4*8+offes_fltregs)(sp)
+ sdc1 $f6 ,( 6*8+offes_fltregs)(sp)
+ sdc1 $f8 ,( 8*8+offes_fltregs)(sp)
+ sdc1 $f10,(10*8+offes_fltregs)(sp)
+ sdc1 $f12,(12*8+offes_fltregs)(sp)
+ sdc1 $f14,(14*8+offes_fltregs)(sp)
+ sdc1 $f16,(16*8+offes_fltregs)(sp)
+ sdc1 $f18,(18*8+offes_fltregs)(sp)
+ sdc1 $f20,(20*8+offes_fltregs)(sp)
+ sdc1 $f22,(22*8+offes_fltregs)(sp)
+ sdc1 $f24,(24*8+offes_fltregs)(sp)
+ sdc1 $f26,(26*8+offes_fltregs)(sp)
+ sdc1 $f28,(28*8+offes_fltregs)(sp)
+ sdc1 $f30,(30*8+offes_fltregs)(sp)
+
+#endif /* SIZEOF_VOID_P == 8 */
+
+ /* calculate sp of method */
+ aaddiu itmp1,sp,(REPLACEMENT_STACK_OFFSET + 2*8)
+ ast itmp1,(offes_sp)(sp)
-nb_aastore_null:
- ald xptr,proto_java_lang_NullPointerException
- move xpc,ra /* faulting address is return adress */
- b asm_handle_nat_exception
+ /* store pv */
+ ast pv,(offes_pv)(sp)
-nb_aastore_bound:
- ald xptr,proto_java_lang_ArrayIndexOutOfBoundsException
- aaddiu sp,sp,32 /* free stack space */
- move xpc,ra /* faulting address is return adress */
- b asm_handle_nat_exception
+ /* call replace_me */
+ ald a0,-(2*8)(itmp1) /* arg0: rplpoint * */
+ move a1,sp /* arg1: execution state */
+ jal replace_me /* call C function replace_me */
+ jal abort /* NEVER REACHED */
-nb_aastore_throw:
- ald xptr,proto_java_lang_ArrayStoreException
- move xpc,ra /* faulting address is return adress */
- b asm_handle_nat_exception
+ .end asm_replacement_out
- .end asm_builtin_aastore
+/* asm_replacement_in **********************************************************
+ This code writes the given execution state and jumps to the replacement
+ code.
-/******************* function asm_initialize_thread_stack **********************
-* *
-* u1* asm_initialize_thread_stack (void *func, u1 *stack); *
-* *
-* initialize a thread stack *
-* *
-*******************************************************************************/
+ This function never returns!
- .ent asm_initialize_thread_stack
-asm_initialize_thread_stack:
-
- aaddiu a1,a1,-14*8 /* allocate save area */
- sd zero, 0*8(a1) /* s0 initalize thread area */
- sd zero, 1*8(a1) /* s1 */
- sd zero, 2*8(a1) /* s2 */
- sd zero, 3*8(a1) /* s3 */
- sd zero, 4*8(a1) /* s4 */
- sd zero, 5*8(a1) /* s5 */
- sd zero, 6*8(a1) /* s6 */
- sd zero, 7*8(a1) /* s7 */
- sd zero, 8*8(a1) /* s8 */
- sd zero, 9*8(a1) /* fs0 */
- sd zero,10*8(a1) /* fs1 */
- sd zero,11*8(a1) /* fs2 */
- sd zero,12*8(a1) /* fs3 */
- sd a0, 13*8(a1)
- move v0,a1
- j ra /* return */
- .end asm_initialize_thread_stack
-
-
-/******************* function asm_perform_threadswitch *************************
-* *
-* void asm_perform_threadswitch (u1 **from, u1 **to, u1 **stackTop); *
-* *
-* performs a threadswitch *
-* *
-*******************************************************************************/
+ NOTE: itmp3 is not restored!
+
+ C prototype:
+ void asm_replacement_in(executionstate *es);
- .ent asm_perform_threadswitch
-asm_perform_threadswitch:
-
- aaddiu sp,sp,-14*8 /* allocate new stack */
- sd s0, 0*8(sp) /* save saved registers of old thread */
- sd s1, 1*8(sp)
- sd s2, 2*8(sp)
- sd s3, 3*8(sp)
- sd s4, 4*8(sp)
- sd s5, 5*8(sp)
- sd s6, 6*8(sp)
- sd s7, 7*8(sp)
- sd s8, 8*8(sp)
- sdc1 fs0, 9*8(sp)
- sdc1 fs1,10*8(sp)
- sdc1 fs2,11*8(sp)
- sdc1 fs3,12*8(sp)
- sd ra, 13*8(sp)
- ast sp,0(a0) /* save old stack pointer */
- ast sp,0(a2) /* stackTop = old stack pointer */
- ald sp,0(a1) /* load new stack pointer */
- ld s0, 0*8(sp) /* load saved registers of new thread */
- ld s1, 1*8(sp)
- ld s2, 2*8(sp)
- ld s3, 3*8(sp)
- ld s4, 4*8(sp)
- ld s5, 5*8(sp)
- ld s6, 6*8(sp)
- ld s7, 7*8(sp)
- ld s8, 8*8(sp)
- ldc1 fs0, 9*8(sp)
- ldc1 fs1,10*8(sp)
- ldc1 fs2,11*8(sp)
- ldc1 fs3,12*8(sp)
- ld ra, 13*8(sp)
- aaddiu sp,sp,14*8 /* deallocate new stack */
- move itmp3, ra
- j ra /* return */
- .end asm_perform_threadswitch
-
-
-/********************* function asm_switchstackandcall *************************
-* *
-* void asm_switchstackandcall (void *stack, void *func, void **stacktopsave); *
-* *
-* 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 *
-* *
*******************************************************************************/
+ .ent asm_replacement_in
+
+asm_replacement_in:
+ /* a0 == executionstate *es */
- .ent asm_switchstackandcall
-asm_switchstackandcall:
- aaddiu a0,a0,-16 /* allocate new stack */
- sd ra,0(a0) /* save return address on new stack */
- sd sp,8(a0) /* save old stack pointer on new stack */
- sd sp,0(a2) /* save old stack pointer to variable */
- move sp,a0 /* switch to new stack */
+ /* set new sp and pv */
+ ald sp,(offes_sp)(a0)
+ ald pv,(offes_pv)(a0)
+
+ /* copy registers from execution state */
+ /* $0 is zero */
+ ald $1 ,( 1*8+offes_intregs)(a0)
+ ald $2 ,( 2*8+offes_intregs)(a0)
+ ald $3 ,( 2*8+offes_intregs)(a0)
+ /* a0 is loaded below */
+ ald $5 ,( 5*8+offes_intregs)(a0)
+ ald $6 ,( 6*8+offes_intregs)(a0)
+ ald $7 ,( 7*8+offes_intregs)(a0)
+ ald $8 ,( 8*8+offes_intregs)(a0)
+ ald $9 ,( 9*8+offes_intregs)(a0)
+ ald $10,(10*8+offes_intregs)(a0)
+ ald $11,(11*8+offes_intregs)(a0)
+ ald $12,(12*8+offes_intregs)(a0)
+ ald $13,(13*8+offes_intregs)(a0)
+ ald $14,(14*8+offes_intregs)(a0)
+ ald $15,(15*8+offes_intregs)(a0)
+ ald $16,(16*8+offes_intregs)(a0)
+ ald $17,(17*8+offes_intregs)(a0)
+ ald $18,(18*8+offes_intregs)(a0)
+ ald $19,(19*8+offes_intregs)(a0)
+ ald $20,(20*8+offes_intregs)(a0)
+ ald $21,(21*8+offes_intregs)(a0)
+ ald $22,(22*8+offes_intregs)(a0)
+ ald $23,(23*8+offes_intregs)(a0)
+ ald $24,(24*8+offes_intregs)(a0)
+ ald $25,(25*8+offes_intregs)(a0)
+ ald $26,(26*8+offes_intregs)(a0)
+ ald $27,(27*8+offes_intregs)(a0)
+ ald $28,(28*8+offes_intregs)(a0)
+ /* $29 is sp */
+ /* $30 is pv */
+ ald $31,(31*8+offes_intregs)(a0)
- move itmp3,a1
- move a0,a3
- jalr itmp3 /* and call function */
+#if SIZEOF_VOID_P == 8
+
+ ldc1 $f0 ,( 0*8+offes_fltregs)(a0)
+ ldc1 $f1 ,( 1*8+offes_fltregs)(a0)
+ ldc1 $f2 ,( 2*8+offes_fltregs)(a0)
+ ldc1 $f3 ,( 3*8+offes_fltregs)(a0)
+ ldc1 $f4 ,( 4*8+offes_fltregs)(a0)
+ ldc1 $f5 ,( 5*8+offes_fltregs)(a0)
+ ldc1 $f6 ,( 6*8+offes_fltregs)(a0)
+ ldc1 $f7 ,( 7*8+offes_fltregs)(a0)
+ ldc1 $f8 ,( 8*8+offes_fltregs)(a0)
+ ldc1 $f9 ,( 9*8+offes_fltregs)(a0)
+ ldc1 $f10,(10*8+offes_fltregs)(a0)
+ ldc1 $f11,(11*8+offes_fltregs)(a0)
+ ldc1 $f12,(12*8+offes_fltregs)(a0)
+ ldc1 $f13,(13*8+offes_fltregs)(a0)
+ ldc1 $f14,(14*8+offes_fltregs)(a0)
+ ldc1 $f15,(15*8+offes_fltregs)(a0)
+ ldc1 $f16,(16*8+offes_fltregs)(a0)
+ ldc1 $f17,(17*8+offes_fltregs)(a0)
+ ldc1 $f18,(18*8+offes_fltregs)(a0)
+ ldc1 $f19,(19*8+offes_fltregs)(a0)
+ ldc1 $f20,(20*8+offes_fltregs)(a0)
+ ldc1 $f21,(21*8+offes_fltregs)(a0)
+ ldc1 $f22,(22*8+offes_fltregs)(a0)
+ ldc1 $f23,(23*8+offes_fltregs)(a0)
+ ldc1 $f24,(24*8+offes_fltregs)(a0)
+ ldc1 $f25,(25*8+offes_fltregs)(a0)
+ ldc1 $f26,(26*8+offes_fltregs)(a0)
+ ldc1 $f27,(27*8+offes_fltregs)(a0)
+ ldc1 $f28,(28*8+offes_fltregs)(a0)
+ ldc1 $f29,(29*8+offes_fltregs)(a0)
+ ldc1 $f30,(30*8+offes_fltregs)(a0)
+ ldc1 $f31,(31*8+offes_fltregs)(a0)
+
+#else /* SIZEOF_VOID_P == 8 */
+
+ ldc1 $f0 ,( 0*8+offes_fltregs)(a0)
+ ldc1 $f2 ,( 2*8+offes_fltregs)(a0)
+ ldc1 $f4 ,( 4*8+offes_fltregs)(a0)
+ ldc1 $f6 ,( 6*8+offes_fltregs)(a0)
+ ldc1 $f8 ,( 8*8+offes_fltregs)(a0)
+ ldc1 $f10,(10*8+offes_fltregs)(a0)
+ ldc1 $f12,(12*8+offes_fltregs)(a0)
+ ldc1 $f14,(14*8+offes_fltregs)(a0)
+ ldc1 $f16,(16*8+offes_fltregs)(a0)
+ ldc1 $f18,(18*8+offes_fltregs)(a0)
+ ldc1 $f20,(20*8+offes_fltregs)(a0)
+ ldc1 $f22,(22*8+offes_fltregs)(a0)
+ ldc1 $f24,(24*8+offes_fltregs)(a0)
+ ldc1 $f26,(26*8+offes_fltregs)(a0)
+ ldc1 $f28,(28*8+offes_fltregs)(a0)
+ ldc1 $f30,(30*8+offes_fltregs)(a0)
+
+#endif /* SIZEOF_VOID_P == 8 */
+
+ /* load new pc */
+
+ ald itmp3,offes_pc(a0)
+
+ /* load a0 */
+
+ ald a0,(4*8+offes_intregs)(a0)
+
+ /* jump to new code */
+
+ jr itmp3
- ld ra,0(sp) /* load return address */
- ld sp,8(sp) /* switch to old stack */
+ .end asm_replacement_in
- j ra /* return */
+#endif /* defined(ENABLE_REPLACEMENT) */
- .end asm_switchstackandcall
- .ent asm_getcallingmethod
-asm_getcallingmethod:
- li v0,0
+ .ent asm_getclassvalues_atomic
+
+asm_getclassvalues_atomic:
+_crit_restart:
+_crit_begin:
+ lw t0,offbaseval(a0)
+ lw t1,offdiffval(a0)
+ lw t2,offbaseval(a1)
+_crit_end:
+ sw t0,offcast_super_baseval(a2)
+ sw t1,offcast_super_diffval(a2)
+ sw t2,offcast_sub_baseval(a2)
j ra
- .end asm_getcallingmethod
+
+ .end asm_getclassvalues_atomic
+
+ .data
+
+asm_criticalsections:
+#if defined(ENABLE_THREADS)
+ .dword _crit_begin
+ .dword _crit_end
+ .dword _crit_restart
+#endif
+ .dword 0
+
+
+ .text
+
+ .ent compare_and_swap
+
+compare_and_swap:
+1:
+ all v0,0(a0)
+ bne v0,a1,2f
+ move t0,a2
+ asc t0,0(a0)
+ beqz t0,1b
+2:
+ sync
+ j ra
+
+ .end compare_and_swap
+
+
+/* Disable exec-stacks, required for Gentoo ***********************************/
+
+#if defined(__GCC__) && defined(__ELF__)
+ .section .note.GNU-stack,"",@progbits
+#endif
/*
* c-basic-offset: 4
* tab-width: 4
* End:
+ * vim:noexpandtab:sw=4:ts=4:
*/