.globl asm_vm_call_method_end
.globl asm_vm_call_method_exception_handler
-.globl asm_call_jit_compiler
-
.globl asm_abstractmethoderror
.globl asm_handle_exception
movel %sp@(12*4+6*8+2*4),%a2 /* arg array */
movel %sp@(12*4+6*8+3*4),%d2 /* arg count */
- movel %a3, %sp@(11*4+6*8) /* copy method address to stackslot */
- leal %sp@(11*4+6*8), %a3 /* and store that address in %a3 */
+ movel %a3, %sp@(12*4+6*8) /* copy method address to stackslot */
+ leal %sp@(12*4+6*8), %a3 /* and store that address in %a3 */
#endif
moveal %sp, %a5 /* memorize stack */
jmp L_asm_vm_call_method_return
-/* asm_call_jit_compiler ************************************************************************************
- * Invokes compiler for untranslated java methods.
- * C prototype: void asm_call_jit_compiler(void);
- * BUT: this does not match reality, arguments _ARE_ passed via createcompilerstub and asm_vm_call_method...
- * arguments passed via %a2(methodinfo) == REG_ATMP1
- * %a3(mptr) == REG_ATMP2
- ************************************************************************************************************/
-asm_call_jit_compiler:
- addal #(-4*4),%sp /* create stackframe to save registers */
- moveml %a0/%a1/%d0/%d1,%sp@ /* save volatile registers */
-#if !defined(ENABLE_SOFTFLOAT)
- addal #-8*2, %sp
- fmovemd %fp0/%fp1, %sp@
- movel %sp@(8*4), %sp@-
- pea %sp@(8*4+8)
-#else
- movel %sp@(4*4), %sp@- /* push arguments onto stack (ra)*/
- pea %sp@(4*4+8) /* the old stack pointer*/
-#endif
- movel %a3,%sp@- /* mptr */
- movel %a2,%sp@- /* methodinfo */
-
- /* C prototype: u1 *jit_asm_compile(methodinfo *m, u1 *mptr, u1 *sp, u1 *ra); */
- jsr jit_asm_compile /* invoke compiler */
- addal #(4*4),%sp /* pop arguments off stack */
- moveal %d0, %a2 /* to tmp register */
-
-#if !defined(ENABLE_SOFTFLOAT)
- fmovemd %sp@, %fp0/%fp1
- addal #8*2, %sp
-#endif
-
- moveml %sp@,%a0/%a1/%d0/%d1 /* restore volatile registers */
- addal #(4*4),%sp /* remove stackframe */
-
- tstl %a2 /* check for exception */
- beq L_asm_call_jit_compiler_exception
-
- jmp %a2@ /* invoke java method */
- jsr 0 /* we should not ever return here */
-
-L_asm_call_jit_compiler_exception:
- jsr exceptions_get_and_clear_exception /* exception object in %d0 now */
- moveal %d0, %a2 /* move exception object into sptr register */
- moveal %sp@+, %a3 /* pop return address into exception address reg */
- jmp asm_handle_exception /* handle exception */
-
-
-
asm_abstractmethoderror:
/* asm_handle_exception ********************************************************
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
constant_classref *cr = iptr->sx.val.c.ref;;
- codegen_addpatchref(cd, PATCHER_resolve_classref_to_classinfo, cr, 0);
+ patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo, cr, 0);
M_AMOV_IMM(0, d);
} else {
M_AMOV_IMM(iptr->sx.val.anyptr, d);
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
unresolved_class *uc = iptr->sx.s23.s2.uc;
- codegen_addpatchref(cd, PATCHER_resolve_class, uc, 0);
+ patcher_add_patch_ref(jd, PATCHER_resolve_class, uc, 0);
}
#endif /* ENABLE_VERIFIER */
M_JSR_PCREL(2); /* get current PC */
fieldtype = uf->fieldref->parseddesc.fd->type;
disp = 0;
- codegen_addpatchref(cd, PATCHER_get_putstatic, uf, 0);
+ patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, 0);
}
else {
fi = iptr->sx.s23.s3.fmiref->p.field;
disp = (intptr_t) fi->value;
if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
- codegen_addpatchref(cd, PATCHER_initialize_class, fi->class,
+ patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->class,
0);
}
}
fieldtype = uf->fieldref->parseddesc.fd->type;
disp = 0;
- codegen_addpatchref(cd, PATCHER_get_putstatic, uf, 0);
+ patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, 0);
}
else {
fi = iptr->sx.s23.s3.fmiref->p.field;
disp = (intptr_t) fi->value;
if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
- codegen_addpatchref(cd, PATCHER_initialize_class, fi->class,
+ patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->class,
0);
}
fieldtype = uf->fieldref->parseddesc.fd->type;
disp = 0;
- codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0);
+ patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
}
else {
fi = iptr->sx.s23.s3.fmiref->p.field;
}
if (INSTRUCTION_IS_UNRESOLVED(iptr))
- codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0);
+ patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
/* implicit null-pointer check */
switch (fieldtype) {
/* fall through */
case ICMD_INVOKESTATIC:
if (lm == NULL) {
- codegen_addpatchref(cd, PATCHER_invokestatic_special, um, 0);
+ patcher_add_patch_ref(jd, PATCHER_invokestatic_special, um, 0);
disp = 0;
M_AMOV_IMM(disp, REG_ATMP1);
} else {
case ICMD_INVOKEVIRTUAL:
if (lm == NULL) {
- codegen_addpatchref(cd, PATCHER_invokevirtual, um, 0);
+ patcher_add_patch_ref(jd, PATCHER_invokevirtual, um, 0);
s1 = 0;
} else {
s1 = OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * lm->vftblindex;
break;
case ICMD_INVOKEINTERFACE:
if (lm == NULL) {
- codegen_addpatchref(cd, PATCHER_invokeinterface, um, 0);
+ patcher_add_patch_ref(jd, PATCHER_invokeinterface, um, 0);
s1 = 0;
s2 = 0;
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
unresolved_class *uc = iptr->sx.s23.s2.uc;
- codegen_addpatchref(cd, PATCHER_resolve_class, uc, 0);
+ patcher_add_patch_ref(jd, PATCHER_resolve_class, uc, 0);
}
#endif /* ENABLE_VERIFIER */
goto nowperformreturn;
M_ATST(s1);
emit_label_beq(cd, BRANCH_LABEL_1);
- codegen_addpatchref(cd, PATCHER_resolve_classref_to_flags, iptr->sx.s23.s3.c.ref, 0);
+ patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags, iptr->sx.s23.s3.c.ref, 0);
M_IMOV_IMM32(0, REG_ITMP3);
M_IAND_IMM(ACC_INTERFACE, REG_ITMP3);
if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
if (super == NULL) {
- codegen_addpatchref(cd, PATCHER_instanceof_interface, iptr->sx.s23.s3.c.ref, 0);
+ patcher_add_patch_ref(jd, PATCHER_instanceof_interface, iptr->sx.s23.s3.c.ref, 0);
} else {
M_ATST(s1);
emit_label_beq(cd, BRANCH_LABEL_3);
if (super == NULL) {
emit_label(cd, BRANCH_LABEL_2);
- codegen_addpatchref(cd, PATCHER_resolve_classref_to_vftbl, iptr->sx.s23.s3.c.ref, 0);
+ patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_vftbl, iptr->sx.s23.s3.c.ref, 0);
M_AMOV_IMM(0, REG_ATMP2);
} else {
M_AMOV_IMM(super->vftbl, REG_ATMP2);
M_ATST(s1);
emit_label_beq(cd, BRANCH_LABEL_1);
- codegen_addpatchref(cd, PATCHER_resolve_classref_to_flags, iptr->sx.s23.s3.c.ref, 0);
+ patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags, iptr->sx.s23.s3.c.ref, 0);
M_IMOV_IMM32(0, REG_ITMP2);
M_IAND_IMM(ACC_INTERFACE, REG_ITMP2);
if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
if (super == NULL) {
- codegen_addpatchref(cd, PATCHER_checkcast_interface, iptr->sx.s23.s3.c.ref, 0);
+ patcher_add_patch_ref(jd, PATCHER_checkcast_interface, iptr->sx.s23.s3.c.ref, 0);
} else {
M_ATST(s1);
emit_label_beq(cd, BRANCH_LABEL_3);
if (super == NULL) {
emit_label(cd, BRANCH_LABEL_2);
- codegen_addpatchref(cd, PATCHER_resolve_classref_to_vftbl, iptr->sx.s23.s3.c.ref, 0);
+ patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_vftbl, iptr->sx.s23.s3.c.ref, 0);
M_AMOV_IMM(0, REG_ATMP3);
} else {
M_AMOV_IMM(super->vftbl, REG_ATMP3);
s1 = emit_load_s1(jd, iptr, REG_ATMP2);
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
- codegen_addpatchref(cd, PATCHER_resolve_classref_to_classinfo, iptr->sx.s23.s3.c.ref, 0);
+ patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo, iptr->sx.s23.s3.c.ref, 0);
M_AMOV_IMM(0, REG_ATMP1);
} else {
M_AMOV_IMM(iptr->sx.s23.s3.c.cls, REG_ATMP1);
/* a1 = arraydescriptor */
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
- codegen_addpatchref(cd, PATCHER_resolve_classref_to_classinfo, iptr->sx.s23.s3.c.ref, 0);
+ patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo, iptr->sx.s23.s3.c.ref, 0);
M_AMOV_IMM(0, REG_ATMP1);
} else {
M_AMOV_IMM(iptr->sx.s23.s3.c.cls, REG_ATMP1);
return true;
}
-
-
+#if 0
/* codegen_emit_stub_compiler **************************************************
Emits a stub routine which calls the compiler.
M_AMOV_IMM(asm_call_jit_compiler, REG_ATMP3);
M_JMP(REG_ATMP3);
}
+#endif
+
/* codegen_emit_stub_native ****************************************************
Emits a stub routine which calls a native method.
/* create method header */
(void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
- (void) dseg_add_unique_s4(cd, cd->stackframesize * 4); /* FrameSize */
+ (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */
(void) dseg_add_unique_s4(cd, 0); /* IsSync */
(void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
(void) dseg_add_unique_s4(cd, 0); /* IntSave */
#endif
/* generate code */
- M_AADD_IMM(-(cd->stackframesize*4), REG_SP);
+ M_AADD_IMM(-(cd->stackframesize*8), REG_SP);
/* get function address (this must happen before the stackframeinfo) */
if (f == NULL) {
- codegen_addpatchref(cd, PATCHER_resolve_native_function, m, 0);
+ patcher_add_patch_ref(jd, PATCHER_resolve_native_function, m, 0);
}
M_AMOV_IMM(f, REG_ATMP2); /* do not move this line, the patcher is needed */
/* all arguments via stack */
assert(md->params[i].inmemory);
- s1 = md->params[i].regoff + cd->stackframesize * 4 + 4;
+ s1 = md->params[i].regoff + cd->stackframesize * 8 + 4;
s2 = nmd->params[j].regoff;
/* simply copy argument stack */
/* natives return float arguments in %d0, %d1, cacao expects them in %fp0 */
case TYPE_DBL:
case TYPE_LNG:
- M_IST(REG_D1, REG_SP, 2 * 4);
+ M_IST(REG_D1, REG_SP, 2 * 8);
/* fall through */
case TYPE_FLT:
case TYPE_INT:
case TYPE_ADR:
- M_IST(REG_D0, REG_SP, 2 * 4);
+ M_IST(REG_D0, REG_SP, 2 * 8); /* XXX can this be correct ? */
break;
default: assert(0);
case TYPE_VOID: break;
case TYPE_DBL:
- case TYPE_LNG:
- M_ILD(REG_D1, REG_SP, 2 * 4);
+ case TYPE_LNG: M_ILD(REG_D1, REG_SP, 2 * 8);
/* fall through */
case TYPE_FLT:
case TYPE_INT:
case TYPE_ADR:
- M_ILD(REG_D0, REG_SP, 2 * 4);
+ M_ILD(REG_D0, REG_SP, 2 * 8); /* XXX */
break;
default: assert(0);
* as cacao jit code expects them there */
switch (md->returntype.type) {
case TYPE_FLT:
- M_FLD(REG_D0, REG_SP, 2 * 4);
+ M_FLD(REG_D0, REG_SP, 2 * 8);
break;
case TYPE_DBL:
- M_DLD(REG_D0, REG_SP, 2 * 4);
+ M_DLD(REG_D0, REG_SP, 2 * 8); /* XXX */
break;
}
#endif
/* restore saved registers */
- M_AADD_IMM(cd->stackframesize*4, REG_SP);
+ M_AADD_IMM(cd->stackframesize*8, REG_SP);
/* check for exception */
M_ATST(REG_ATMP1);
M_BNE(2);
#include "vm/exceptions.h"
#include "vm/jit/asmpart.h"
#include "vm/builtin.h"
+#include "vm/jit/trace.h"
#include "mm/memory.h"
codegendata *cd;
registerdata *rd;
methoddesc *md;
- s4 disp,i,t;
-
if (!JITDATA_HAS_FLAG_VERBOSECALL(jd))
return;
M_IPUSH(REG_D1);
M_APUSH(REG_A0);
M_APUSH(REG_A1);
+ M_AMOV(REG_SP, REG_A0); /* simpyfy stack offset calculation */
#if !defined(ENABLE_SOFTFLOAT)
M_AADD_IMM(-8*2, REG_SP);
M_FSTORE(REG_F0, REG_SP, 8);
M_FSTORE(REG_F1, REG_SP, 0);
-
- disp = 4*4 + 8*2 + 4; /* points to old argument stack initially */
-#else
- disp = 4*4 + 4;
#endif
- /* builtin_verbosecall_enter takes all args as s8 type */
- /* TRACE_ARGS_NUM is the number of args the builtin_verbosecall_enter expects */
- M_IPUSH_IMM(m);
-
- /* travel up stack to the first argument of the function which needs to be copied */
- for (i=0; (i < md->paramcount) && (i < TRACE_ARGS_NUM); i++) {
- disp += 8;
- }
-
- /* disp now points to the first arg which gets copied to the trace stack, relative to REG_SP! */
- for (i=TRACE_ARGS_NUM-1; i>=0; --i) {
- if (i < md->paramcount) {
- /* traced function has such an argument */
- t = md->paramtypes[i].type;
-
- /* copy from original argument stack */
- M_ILD(REG_ITMP1, REG_SP, disp);
- M_ILD(REG_ITMP2, REG_SP, disp-4);
- M_IPUSH(REG_ITMP2);
- M_IPUSH(REG_ITMP1);
- } else {
- /* function has no arg here, push nothing and adapt displacement */
- M_IPUSH_IMM(0);
- M_IPUSH_IMM(0);
- disp += 8;
- }
- }
- M_JSR_IMM(builtin_verbosecall_enter);
+ M_AADD_IMM(4*4 + 4, REG_A0);
+ M_APUSH(REG_A0); /* third arg is original argument stack */
+ M_IPUSH_IMM(0); /* second arg is number of argument registers (=0) */
+ M_IPUSH_IMM(m); /* first arg is methodpointer */
+
+ M_JSR_IMM(trace_java_call_enter);
/* pop arguments off stack */
- M_AADD_IMM(TRACE_ARGS_NUM*8+4, REG_SP);
+ M_AADD_IMM(3*4, REG_SP);
#if !defined(ENABLE_SOFTFLOAT)
M_FSTORE(REG_F1, REG_SP, 0);
}
}
+/* emit_trap_compiler **********************************************************
+
+ Emit a trap instruction which calls the JIT compiler.
+
+*******************************************************************************/
+
+void emit_trap_compiler(codegendata *cd)
+{
+ M_TRAP_SETREGISTER(REG_METHODPTR);
+ M_TRAP(EXCEPTION_HARDWARE_COMPILER);
+}
+
+
+/* emit_trap *******************************************************************
+
+ Emit a trap instruction and return the original machine code.
+
+*******************************************************************************/
+
+uint32_t emit_trap(codegendata *cd)
+{
+ uint16_t mcode;
+
+ /* Get machine code which is patched back in later. The
+ trap is 2 bytes long. */
+
+ mcode = *((uint16_t *) cd->mcodeptr);
+
+ M_TRAP(EXCEPTION_HARDWARE_PATCHER);
+
+ return (uint32_t) mcode;
+}
+
+
/*
* These are local overrides for various environment variables in Emacs.
} actual_ucontext_t;
-/*
- * linux specific initializations
- */
-void md_init_linux()
-{
- struct sigaction act;
-
- act.sa_sigaction = md_signal_handler_sigill;
- act.sa_flags = SA_NODEFER | SA_SIGINFO;
-
- if (sigaction(SIGILL, &act, NULL) == -1) {
- vm_abort("md_linux_init: Error registering signal handler");
- }
-}
/* md_signal_handler_sigsegv ******************************************
*
**********************************************************************/
void md_signal_handler_sigill(int sig, siginfo_t *siginfo, void *_p)
{
- uint32_t xpc, sp;
+ uint32_t xpc, sp, ra, pv;
uint16_t opc;
uint32_t type;
- uint32_t val, regval;
+ uint32_t regval;
void *p;
actual_mcontext_t *_mc;
actual_ucontext_t *_uc;
_uc = (actual_ucontext_t*)_p;
xpc = (uint32_t)siginfo->si_addr;
+ pv = NULL; /* we have no pv */
+ ra = xpc; /* that is ture for most cases */
+
if (siginfo->si_code == ILL_ILLOPC) {
vm_abort("md_signal_handler_sigill: the illegal instruction @ 0x%x, aborting", xpc);
}
case M68K_EXCEPTION_HARDWARE_NULLPOINTER:
type = EXCEPTION_HARDWARE_NULLPOINTER;
break;
+ case EXCEPTION_HARDWARE_COMPILER:
+ regval = *(uint16_t*)(xpc-4);
+ assert( (regval&0xfff0) == 0x4a00 );
+ /* was in a address register */
+ regval = _mc->gregs[ GREGS_ADRREG_OFF + (regval & 0x7) ];
+
+ pv = xpc-4; /* the compiler stub consists of 2 instructions */
+ ra = md_stacktrace_get_returnaddress(sp, 0);
+ sp = sp + SIZEOF_VOID_P;
+ xpc = ra - 2;
+ break;
+ case EXCEPTION_HARDWARE_PATCHER:
+ xpc -= 2;
+ break;
default: assert(0);
}
*/
/* Handle the type. */
+ p = signal_handle(type, regval, pv, (void*)sp, (void*)ra, (void*)xpc, _p);
- p = signal_handle(type, val, NULL, (void*)sp, (void*)xpc, (void*)xpc, _p);
- _mc->gregs[GREGS_ADRREG_OFF + REG_ATMP1] = (intptr_t) p;
- _mc->gregs[GREGS_ADRREG_OFF + REG_ATMP2_XPC] = (intptr_t) xpc;
- _mc->gregs[R_PC] = (intptr_t) asm_handle_exception;
+ if (type == EXCEPTION_HARDWARE_COMPILER) {
+ if (p == NULL) {
+ /* exception when compiling the method */
+ java_object_t *o = exceptions_get_and_clear_exceptions();
+
+ _mc->gregs[R_SP] = sp; /* remove RA from stack */
+
+ _mc->gregs[GREGS_ADRREG_OFF + REG_ATMP1] = (intptr_t) o;
+ _mc->gregs[GREGS_ADRREG_OFF + REG_ATMP2_XPC] = (intptr_t) xpc;
+ _mc->gregs[R_PC] = (intptr_t) asm_handle_exception;
+
+ } else {
+ /* compilation ok, execute */
+ _mc->gregs[R_PC] = p;
+ }
+
+ } else {
+ _mc->gregs[GREGS_ADRREG_OFF + REG_ATMP1] = (intptr_t) p;
+ _mc->gregs[GREGS_ADRREG_OFF + REG_ATMP2_XPC] = (intptr_t) xpc;
+ _mc->gregs[R_PC] = (intptr_t) asm_handle_exception;
+ }
}
/* md_signal_handler_sigusr1 ***************************************************