This module generates MIPS machine code for a sequence of
intermediate code commands (ICMDs).
- $Id: codegen.c 4530 2006-02-21 09:11:53Z twisti $
+ $Id: codegen.c 4654 2006-03-19 19:46:11Z edwin $
*/
#include "vm/jit/jit.h"
#include "vm/jit/patcher.h"
#include "vm/jit/reg.h"
+#include "vm/jit/replace.h"
#if defined(ENABLE_LSRA)
# include "vm/jit/allocator/lsra.h"
methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
builtintable_entry *bte;
methoddesc *md;
+ rplpoint *replacementpoint;
{
s4 i, p, t, l;
s1 = rd->memuse;
- if (runverbose) {
+ if (opt_verbosecall) {
M_LDA(REG_SP, REG_SP, -(INT_ARG_CNT + FLT_ARG_CNT) * 8);
for (p = 0; p < INT_ARG_CNT; p++)
} else {
M_BEQZ(rd->argintregs[0], 0);
- codegen_addxnullrefs(cd, mcodeptr);
+ codegen_add_nullpointerexception_ref(cd, mcodeptr);
p = dseg_addaddress(cd, BUILTIN_monitorenter);
M_ALD(REG_ITMP3, REG_PV, p);
M_JSR(REG_RA, REG_ITMP3);
M_AST(rd->argintregs[0], REG_SP, s1 * 8); /* branch delay */
}
- if (runverbose) {
+ if (opt_verbosecall) {
for (p = 0; p < INT_ARG_CNT; p++)
M_LLD(rd->argintregs[p], REG_SP, p * 8);
/* copy argument registers to stack and call trace function */
- if (runverbose) {
+ if (opt_verbosecall) {
M_LDA(REG_SP, REG_SP, -(2 + INT_ARG_CNT + FLT_ARG_CNT + INT_TMP_CNT + FLT_TMP_CNT) * 8);
M_AST(REG_RA, REG_SP, 1 * 8);
/* end of header generation */
+ replacementpoint = cd->code->rplpoints;
+
/* walk through all basic blocks */
for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
+ /* handle replacement points */
+
+ if (bptr->bitflags & BBFLAG_REPLACEMENT && bptr->flags >= BBREACHED) {
+
+ /* 8-byte align pc */
+ if ((ptrint)mcodeptr & 4) {
+ M_NOP;
+ }
+
+ replacementpoint->pc = (u1*)(ptrint)((u1*)mcodeptr - cd->mcodebase);
+ replacementpoint++;
+
+ assert(cd->lastmcodeptr <= (u1*)mcodeptr);
+ cd->lastmcodeptr = (u1*)cd->mcodeptr + 2*4; /* br + delay slot */
+ }
+
+ /* store relative start of block */
+
bptr->mpc = (s4) ((u1 *) mcodeptr - cd->mcodebase);
if (bptr->flags >= BBREACHED) {
var_to_reg_int(s1, src, REG_ITMP1);
M_BEQZ(s1, 0);
- codegen_addxnullrefs(cd, mcodeptr);
+ codegen_add_nullpointerexception_ref(cd, mcodeptr);
M_NOP;
break;
M_NOP;
M_BEQZ(REG_RESULT, 0);
- codegen_addxstorerefs(cd, mcodeptr);
+ codegen_add_arraystoreexception_ref(cd, mcodeptr);
M_NOP;
var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
/* call trace function */
- if (runverbose) {
+ if (opt_verbosecall) {
M_LDA(REG_SP, REG_SP, -3 * 8);
M_LST(REG_RA, REG_SP, 0 * 8);
M_LST(REG_RESULT, REG_SP, 1 * 8);
if (iptr->op1 == true) {
M_BEQZ(REG_RESULT, 0);
- codegen_addxexceptionrefs(cd, mcodeptr);
+ codegen_add_fillinstacktrace_ref(cd, mcodeptr);
M_NOP;
}
break;
case ICMD_INVOKESPECIAL:
M_BEQZ(rd->argintregs[0], 0);
- codegen_addxnullrefs(cd, mcodeptr);
+ codegen_add_nullpointerexception_ref(cd, mcodeptr);
M_NOP;
/* fall through */
M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
M_IADD_IMM(REG_ITMP3, -superindex, REG_ITMP3);
M_BLEZ(REG_ITMP3, 0);
- codegen_addxcastrefs(cd, mcodeptr);
+ codegen_add_classcastexception_ref(cd, mcodeptr);
M_NOP;
M_ALD(REG_ITMP3, REG_ITMP2,
OFFSET(vftbl_t, interfacetable[0]) -
superindex * sizeof(methodptr*));
M_BEQZ(REG_ITMP3, 0);
- codegen_addxcastrefs(cd, mcodeptr);
+ codegen_add_classcastexception_ref(cd, mcodeptr);
M_NOP;
if (!super) {
/* } */
M_CMPULT(REG_ITMP3, REG_ITMP2, REG_ITMP3);
M_BNEZ(REG_ITMP3, 0);
- codegen_addxcastrefs(cd, mcodeptr);
+ codegen_add_classcastexception_ref(cd, mcodeptr);
M_NOP;
}
d = reg_of_var(rd, iptr->dst, s1);
M_NOP;
M_BEQZ(REG_RESULT, 0);
- codegen_addxcastrefs(cd, mcodeptr);
+ codegen_add_classcastexception_ref(cd, mcodeptr);
M_NOP;
var_to_reg_int(s1, src, REG_ITMP1);
/* check for exception before result assignment */
M_BEQZ(REG_RESULT, 0);
- codegen_addxexceptionrefs(cd, mcodeptr);
+ codegen_add_fillinstacktrace_ref(cd, mcodeptr);
M_NOP;
d = reg_of_var(rd, iptr->dst, REG_RESULT);
dseg_createlinenumbertable(cd);
+#if 0
{
s4 *xcodeptr;
branchref *bref;
M_NOP;
}
}
+#endif
- /* generate patcher stub call code */
+
+ /* generate exception and patcher stubs */
{
- patchref *pref;
- u8 mcode;
- s4 *tmpmcodeptr;
+ exceptionref *eref;
+ patchref *pref;
+ u8 mcode;
+ s4 *savedmcodeptr;
+ s4 *tmpmcodeptr;
+
+ savedmcodeptr = NULL;
+
+ /* generate exception stubs */
+
+ for (eref = cd->exceptionrefs; eref != NULL; eref = eref->next) {
+ gen_resolvebranch((u1 *) cd->mcodebase + eref->branchpos,
+ eref->branchpos,
+ (u1 *) mcodeptr - cd->mcodebase);
+
+ MCODECHECK(100);
+
+ /* Check if the exception is an
+ ArrayIndexOutOfBoundsException. If so, move index register
+ into REG_ITMP1. */
+
+ if (eref->reg != -1)
+ M_MOV(eref->reg, REG_ITMP1);
+
+ /* calcuate exception address */
+
+ M_LDA(REG_ITMP2_XPC, REG_PV, eref->branchpos - 4);
+
+ /* move function to call into REG_ITMP3 */
+
+ disp = dseg_addaddress(cd, eref->function);
+ M_ALD(REG_ITMP3, REG_PV, disp);
+
+ if (savedmcodeptr != NULL) {
+ M_BR(savedmcodeptr - mcodeptr);
+ M_NOP;
+
+ } else {
+ savedmcodeptr = mcodeptr;
+
+ M_MOV(REG_PV, rd->argintregs[0]);
+ M_MOV(REG_SP, rd->argintregs[1]);
+
+ if (m->isleafmethod)
+ M_MOV(REG_RA, rd->argintregs[2]);
+ else
+ M_ALD(rd->argintregs[2],
+ REG_SP, parentargs_base * 8 - SIZEOF_VOID_P);
+
+ M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
+ M_MOV(REG_ITMP1, rd->argintregs[4]);
+
+ M_ASUB_IMM(REG_SP, 2 * 8, REG_SP);
+ M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
+
+ if (m->isleafmethod)
+ M_AST(REG_RA, REG_SP, 1 * 8);
+
+ M_JSR(REG_RA, REG_ITMP3);
+ M_NOP;
+ M_MOV(REG_RESULT, REG_ITMP1_XPTR);
+
+ if (m->isleafmethod)
+ M_ALD(REG_RA, REG_SP, 1 * 8);
+
+ M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
+ M_AADD_IMM(REG_SP, 2 * 8, REG_SP);
+
+ a = dseg_addaddress(cd, asm_handle_exception);
+ M_ALD(REG_ITMP3, REG_PV, a);
+ M_JMP(REG_ITMP3);
+ M_NOP;
+ }
+ }
+
+
+ /* generate code patching stub call code */
for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
/* check code segment size */
MCODECHECK(100);
- /* Get machine code which is patched back in later. The call is */
- /* 2 instruction words long. */
+ /* Get machine code which is patched back in later. The
+ call is 2 instruction words long. */
- xcodeptr = (s4 *) (cd->mcodebase + pref->branchpos);
+ tmpmcodeptr = (s4 *) (cd->mcodebase + pref->branchpos);
- /* We need to split this, because an unaligned 8 byte read causes */
- /* a SIGSEGV. */
+ /* We need to split this, because an unaligned 8 byte read
+ causes a SIGSEGV. */
- mcode = ((u8) xcodeptr[1] << 32) + (u4) xcodeptr[0];
+ mcode = ((u8) tmpmcodeptr[1] << 32) + (u4) tmpmcodeptr[0];
- /* patch in the call to call the following code (done at compile */
- /* time) */
+ /* Patch in the call to call the following code (done at
+ compile time). */
- tmpmcodeptr = mcodeptr; /* save current mcodeptr */
- mcodeptr = xcodeptr; /* set mcodeptr to patch position */
+ savedmcodeptr = mcodeptr; /* save current mcodeptr */
+ mcodeptr = tmpmcodeptr; /* set mcodeptr to patch position */
- disp = (s4) (tmpmcodeptr - (xcodeptr + 1));
+ disp = (s4) (savedmcodeptr - (tmpmcodeptr + 1));
if ((disp < (s4) 0xffff8000) || (disp > (s4) 0x00007fff)) {
*exceptionptr =
M_BR(disp);
M_NOP;
- mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
+ mcodeptr = savedmcodeptr; /* restore the current mcodeptr */
/* create stack frame */
M_JMP(REG_ITMP3);
M_NOP;
}
- }
+
+ /* generate replacement-out stubs */
+
+ {
+ int i;
+
+ replacementpoint = cd->code->rplpoints;
+ for (i=0; i<cd->code->rplpointcount; ++i, ++replacementpoint) {
+ /* check code segment size */
+
+ MCODECHECK(100);
+
+ /* note start of stub code */
+
+ replacementpoint->outcode = (u1*) (ptrint)((u1*)mcodeptr - cd->mcodebase);
+
+ /* make machine code for patching */
+
+ tmpmcodeptr = mcodeptr;
+ mcodeptr = (s4*) &(replacementpoint->mcode);
+
+ disp = (ptrint)((s4*)replacementpoint->outcode - (s4*)replacementpoint->pc) - 1;
+ if ((disp < (s4) 0xffff8000) || (disp > (s4) 0x00007fff)) {
+ *exceptionptr =
+ new_internalerror("Jump offset is out of range: %d > +/-%d",
+ disp, 0x00007fff);
+ return false;
+ }
+ M_BR(disp);
+ M_NOP; /* delay slot */
+
+ mcodeptr = tmpmcodeptr;
+
+ /* create stack frame - 16-byte aligned */
+
+ M_ASUB_IMM(REG_SP, 2 * 8, REG_SP);
+
+ /* push address of `rplpoint` struct */
+
+ disp = dseg_addaddress(cd, replacementpoint);
+ M_ALD(REG_ITMP3, REG_PV, disp);
+ M_AST(REG_ITMP3, REG_SP, 0 * 8);
+
+ /* jump to replacement function */
+
+ disp = dseg_addaddress(cd, asm_replacement_out);
+ M_ALD(REG_ITMP3, REG_PV, disp);
+ M_JMP(REG_ITMP3);
+ M_NOP; /* delay slot */
+ }
+ }
}
codegen_finish(m, cd, (s4) ((u1 *) mcodeptr - cd->mcodebase));
- docacheflush((void *) m->entrypoint, ((u1 *) mcodeptr - cd->mcodebase));
+ docacheflush((void *) cd->code->entrypoint, ((u1 *) mcodeptr - cd->mcodebase));
/* everything's ok */
/* call trace function */
- if (runverbose) {
+ if (opt_verbosecall) {
M_LDA(REG_SP, REG_SP, -(1 + INT_ARG_CNT + FLT_ARG_CNT) * 8);
/* save integer argument registers */
/* call finished trace function */
- if (runverbose) {
+ if (opt_verbosecall) {
if (IS_INT_LNG_TYPE(md->returntype.type))
M_LLD(REG_RESULT, REG_SP, 0 * 8);
else
{
patchref *pref;
- s4 *xcodeptr;
- s8 mcode;
+ u8 mcode;
+ s4 *savedmcodeptr;
s4 *tmpmcodeptr;
for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
- /* Get machine code which is patched back in later. The call is */
- /* 2 instruction words long. */
+ /* Get machine code which is patched back in later. The
+ call is 2 instruction words long. */
- xcodeptr = (s4 *) (cd->mcodebase + pref->branchpos);
+ tmpmcodeptr = (s4 *) (cd->mcodebase + pref->branchpos);
- /* We need to split this, because an unaligned 8 byte read causes */
- /* a SIGSEGV. */
+ /* We need to split this, because an unaligned 8 byte read
+ causes a SIGSEGV. */
- mcode = ((u8) xcodeptr[1] << 32) + (u4) xcodeptr[0];
+ mcode = ((u8) tmpmcodeptr[1] << 32) + (u4) tmpmcodeptr[0];
- /* patch in the call to call the following code (done at compile */
- /* time) */
+ /* Patch in the call to call the following code (done at
+ compile time). */
- tmpmcodeptr = mcodeptr; /* save current mcodeptr */
- mcodeptr = xcodeptr; /* set mcodeptr to patch position */
+ savedmcodeptr = mcodeptr; /* save current mcodeptr */
+ mcodeptr = tmpmcodeptr; /* set mcodeptr to patch position */
- M_BRS(tmpmcodeptr - (xcodeptr + 1));
+ M_BRS(savedmcodeptr - (tmpmcodeptr + 1));
M_NOP; /* branch delay slot */
- mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
+ mcodeptr = savedmcodeptr; /* restore the current mcodeptr */
/* create stack frame */
codegen_finish(m, cd, (s4) ((u1 *) mcodeptr - cd->mcodebase));
- docacheflush((void *) m->entrypoint, ((u1 *) mcodeptr - cd->mcodebase));
+ docacheflush((void *) cd->code->entrypoint, ((u1 *) mcodeptr - cd->mcodebase));
- return m->entrypoint;
+ return cd->code->entrypoint;
}
* c-basic-offset: 4
* tab-width: 4
* End:
+ * vim:noexpandtab:sw=4:ts=4:
*/