/* src/vm/jit/sparc64/codegen.c - machine code generator for Sparc
- Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+ 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
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- Contact: cacao@cacaojvm.org
-
- Authors: Andreas Krall
- Reinhard Grafl
- Alexander Jordan
-
- Changes: Edwin Steiner
-
$Id: codegen.c 4644 2006-03-16 18:44:46Z edwin $
*/
#include "config.h"
-#include <stdio.h>
#include <assert.h>
-
+#include <stdio.h>
#include "vm/types.h"
#include "vm/builtin.h"
#include "vm/exceptions.h"
#include "vm/global.h"
-#include "vm/loader.h"
-#include "vm/options.h"
-#include "vm/stringlocal.h"
+
#include "vm/jit/asmpart.h"
#include "vm/jit/codegen-common.h"
#include "vm/jit/dseg.h"
#include "vm/jit/emit-common.h"
+#include "vm/jit/sparc64/emit.h"
#include "vm/jit/jit.h"
#include "vm/jit/parse.h"
#include "vm/jit/patcher.h"
#include "vm/jit/reg.h"
+#include "vm/jit/replace.h"
+#include "vm/jit/stacktrace.h"
+#include "vmcore/loader.h"
+#include "vmcore/options.h"
/* XXX use something like this for window control ?
* #define REG_PV (own_window?REG_PV_CALLEE:REG_PV_CALLER)
*/
#define REG_PV REG_PV_CALLEE
-static int fabort(char *x)
+bool fits_13(s4 disp)
+{
+ /*
+ if ((disp < -4096) || (disp > 4095))
+ printf("disp %d\n", disp);
+ */
+
+ return (disp >= -4096) && (disp <= 4095);
+}
+
+s4 get_lopart_disp(disp)
{
- fprintf(stderr, "sparc64 abort because: %s\n", x);
- exit(1);
- abort();
- return 0;
-
+ s4 lodisp;
+
+ if (disp > 0)
+ lodisp = setlo_part(disp);
+ else {
+ if (setlo_part(disp) == 0)
+ lodisp = 0;
+ else
+ lodisp = setlo_part(disp) | 0x1c00;
+ }
+
+ return lodisp;
}
+
-/* codegen *********************************************************************
+/* codegen_emit ****************************************************************
Generates machine code.
*******************************************************************************/
-bool codegen(jitdata *jd)
+bool codegen_emit(jitdata *jd)
{
methodinfo *m;
codeinfo *code;
codegendata *cd;
registerdata *rd;
s4 len, s1, s2, s3, d, disp;
- s4 stackframesize;
- stackptr src;
varinfo *var;
basicblock *bptr;
instruction *iptr;
exception_entry *ex;
u2 currentline;
+ constant_classref *cr;
methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
unresolved_method *um;
builtintable_entry *bte;
methoddesc *md;
- rplpoint *replacementpoint;
+ fieldinfo *fi;
+ unresolved_field *uf;
s4 fieldtype;
+ s4 varindex;
/* get required compiler data */
{
s4 i, p, t, l;
- s4 savedregs_num;
+ s4 savedregs_num, localbase;
#if 0 /* no leaf optimization yet */
savedregs_num = (jd->isleafmethod) ? 0 : 1; /* space to save the RA */
#endif
- savedregs_num = 16; /* register-window save area */
+ savedregs_num = WINSAVE_CNT + ABIPARAMS_CNT; /* register-window save area */
/* space to save used callee saved registers */
savedregs_num += (INT_SAV_CNT - rd->savintreguse);
savedregs_num += (FLT_SAV_CNT - rd->savfltreguse);
- stackframesize = rd->memuse + savedregs_num;
+ cd->stackframesize = rd->memuse + savedregs_num;
#if defined(ENABLE_THREADS) /* space to save argument of monitor_enter */
if (checksync && (m->flags & ACC_SYNCHRONIZED))
- stackframesize++;
+ cd->stackframesize++;
#endif
+ /* keep stack 16-byte aligned (ABI requirement) */
+
+ if (cd->stackframesize & 1)
+ cd->stackframesize++;
+
/* create method header */
-
- (void) dseg_addaddress(cd, code); /* CodeinfoPointer */
- (void) dseg_adds4(cd, stackframesize * 8); /* FrameSize */
+
+ (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
+ (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */
#if defined(ENABLE_THREADS)
/* IsSync contains the offset relative to the stack pointer for the
*/
if (checksync && (m->flags & ACC_SYNCHRONIZED))
- (void) dseg_adds4(cd, (rd->memuse + 1) * 8); /* IsSync */
+ (void) dseg_add_unique_s4(cd, (rd->memuse + 1) * 8); /* IsSync */
else
#endif
- (void) dseg_adds4(cd, 0); /* IsSync */
+ (void) dseg_add_unique_s4(cd, 0); /* IsSync */
- (void) dseg_adds4(cd, jd->isleafmethod); /* IsLeaf */
- (void) dseg_adds4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
- (void) dseg_adds4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
-
+ (void) dseg_add_unique_s4(cd, jd->isleafmethod); /* IsLeaf */
+ (void) dseg_add_unique_s4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
+ (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
dseg_addlinenumbertablesize(cd);
+ (void) dseg_add_unique_s4(cd, jd->exceptiontablelength); /* ExTableSize */
- (void) dseg_adds4(cd, jd->exceptiontablelength); /* ExTableSize */
-
/* create exception table */
for (ex = jd->exceptiontable; ex != NULL; ex = ex->down) {
- dseg_addtarget(cd, ex->start);
- dseg_addtarget(cd, ex->end);
- dseg_addtarget(cd, ex->handler);
- (void) dseg_addaddress(cd, ex->catchtype.any);
+ dseg_add_target(cd, ex->start);
+ dseg_add_target(cd, ex->end);
+ dseg_add_target(cd, ex->handler);
+ (void) dseg_add_unique_address(cd, ex->catchtype.any);
}
/* save register window and create stack frame (if necessary) */
- if (stackframesize)
- M_SAVE(REG_SP, -stackframesize * 8, REG_SP);
+ if (cd->stackframesize)
+ M_SAVE(REG_SP, -cd->stackframesize * 8, REG_SP);
- /* save return address and used callee saved registers */
- p = stackframesize;
+ /* save callee saved float registers (none right now) */
+#if 0
+ p = cd->stackframesize;
for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
- p--; M_DST(rd->savfltregs[i], REG_SP, (WINSAVE_REGS + p) * 8);
- }
+ p--; M_DST(rd->savfltregs[i], REG_SP, USESTACK + (p * 8));
+ }
+#endif
+
+#if !defined(NDEBUG)
+ if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
+ emit_verbosecall_enter(jd);
+#endif
+
+
/* take arguments out of register or stack frame */
-
+
md = m->parseddesc;
+ /* when storing locals, use this as base */
+ localbase = JITSTACK;
+
+ /* since the register allocator does not know about the shifting window
+ * arg regs need to be copied via the stack
+ */
+ if (md->argintreguse > 0) {
+ /* allocate scratch space for copying in to save(i&l) regs */
+ M_SUB_IMM(REG_SP, INT_ARG_CNT * 8, REG_SP);
+
+ localbase += INT_ARG_CNT * 8;
+
+ /* XXX could use the param slots on the stack for this! */
+ for (p = 0; p < INT_ARG_CNT; p++)
+ M_STX(REG_WINDOW_TRANSPOSE(rd->argintregs[p]), REG_SP, JITSTACK + (p * 8));
+ }
+
+
for (p = 0, l = 0; p < md->paramcount; p++) {
t = md->paramtypes[p].type;
- var = &(rd->locals[l][t]);
+
+ varindex = jd->local_map[l * 5 + t];
+
l++;
if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
l++;
- if (var->type < 0)
+
+ if (varindex == UNUSED)
continue;
+
+ var = VAR(varindex);
+
s1 = md->params[p].regoff;
if (IS_INT_LNG_TYPE(t)) { /* integer args */
if (!md->params[p].inmemory) { /* register arguments */
- s2 = rd->argintregs[s1];
+ /*s2 = rd->argintregs[s1];*/
+ /*s2 = REG_WINDOW_TRANSPOSE(s2);*/
if (!(var->flags & INMEMORY)) { /* reg arg -> register */
- M_INTMOVE(s2, var->regoff);
+ /*M_INTMOVE(s2, var->vv.regoff);*/
+ M_LDX(var->vv.regoff, REG_SP, JITSTACK + (s1 * 8));
} else { /* reg arg -> spilled */
- M_STX(s2, REG_SP, (WINSAVE_REGS + var->regoff) * 8);
+ /*M_STX(s2, REG_SP, (WINSAVE_CNT + var->vv.regoff) * 8);*/
+
+ M_LDX(REG_ITMP1, REG_SP, JITSTACK + (s1 * 8));
+ M_STX(REG_ITMP1, REG_SP, localbase + (var->vv.regoff * 8));
}
} else { /* stack arguments */
if (!(var->flags & INMEMORY)) { /* stack arg -> register */
- M_LDX(var->regoff, REG_SP, (stackframesize + s1) * 8);
+ M_LDX(var->vv.regoff, REG_FP, JITSTACK + (s1 * 8));
} else { /* stack arg -> spilled */
- var->regoff = stackframesize + s1;
+ /* add the callers window save registers */
+ var->vv.regoff = cd->stackframesize + s1;
}
}
if (!md->params[p].inmemory) { /* register arguments */
s2 = rd->argfltregs[s1];
if (!(var->flags & INMEMORY)) { /* reg arg -> register */
- M_FLTMOVE(s2, var->regoff);
+ M_FLTMOVE(s2, var->vv.regoff);
} else { /* reg arg -> spilled */
- M_DST(s2, REG_SP, (WINSAVE_REGS + var->regoff) * 8);
+ M_DST(s2, REG_SP, localbase + (var->vv.regoff) * 8);
}
} else { /* stack arguments */
if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
- M_DLD(var->regoff, REG_SP, (stackframesize + s1) * 8);
+ M_DLD(var->vv.regoff, REG_FP, JITSTACK + (s1 * 8));
} else { /* stack-arg -> spilled */
- var->regoff = stackframesize + s1;
+ var->vv.regoff = cd->stackframesize + s1;
}
}
}
} /* end for */
+ if (md->argintreguse > 0) {
+ /* release scratch space */
+ M_ADD_IMM(REG_SP, INT_ARG_CNT * 8, REG_SP);
+ }
+
- /* XXX monitor enter and tracing */
+ /* XXX monitor enter */
+
+
+
}
/* end of header generation */
- replacementpoint = jd->code->rplpoints;
+ /* create replacement points */
+
+ REPLACEMENT_POINTS_INIT(cd, jd);
/* walk through all basic blocks */
/* branch resolving */
- {
- branchref *brefs;
- for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
- gen_resolvebranch((u1*) cd->mcodebase + brefs->branchpos,
- brefs->branchpos, bptr->mpc);
- }
- }
+ codegen_resolve_branchrefs(cd, bptr);
/* handle replacement points */
+#if 0
if (bptr->bitflags & BBFLAG_REPLACEMENT) {
replacementpoint->pc = (u1*)(ptrint)bptr->mpc; /* will be resolved later */
replacementpoint++;
}
+#endif
/* copy interface registers to their destination */
- src = bptr->instack;
len = bptr->indepth;
MCODECHECK(64+len);
#if defined(ENABLE_LSRA)
+#error XXX LSRA not tested yet
if (opt_lsra) {
- while (src != NULL) {
+ while (len) {
len--;
- if ((len == 0) && (bptr->type != BBTYPE_STD)) {
+ src = bptr->invars[len];
+ if ((len == bptr->indepth-1) && (bptr->type == BBTYPE_EXH)) {
/* d = reg_of_var(m, src, REG_ITMP1); */
if (!(src->flags & INMEMORY))
- d = src->regoff;
+ d = src->vv.regoff;
else
d = REG_ITMP1;
M_INTMOVE(REG_ITMP1, d);
emit_store(jd, NULL, src, d);
}
- src = src->prev;
}
} else {
#endif
- while (src != NULL) {
- len--;
- if ((len == 0) && (bptr->type != BBTYPE_STD)) {
- d = codegen_reg_of_var(rd, 0, src, REG_ITMP1);
- M_INTMOVE(REG_ITMP1, d);
- emit_store(jd, NULL, src, d);
-
- } else {
- d = codegen_reg_of_var(rd, 0, src, REG_IFTMP);
- if ((src->varkind != STACKVAR)) {
- s2 = src->type;
- if (IS_FLT_DBL_TYPE(s2)) {
- if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
- s1 = rd->interfaces[len][s2].regoff;
- M_DBLMOVE(s1, d);
- } else {
- M_DLD(d, REG_SP, rd->interfaces[len][s2].regoff * 8);
- }
- emit_store(jd, NULL, src, d);
-
- } else {
- if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
- s1 = rd->interfaces[len][s2].regoff;
- M_INTMOVE(s1, d);
- } else {
- M_LDX(d, REG_SP, rd->interfaces[len][s2].regoff * 8);
- }
- emit_store(jd, NULL, src, d);
- }
- }
- }
- src = src->prev;
+ while (len) {
+ len--;
+ var = VAR(bptr->invars[len]);
+ if ((len == bptr->indepth-1) && (bptr->type == BBTYPE_EXH)) {
+ d = codegen_reg_of_var(0, var, REG_ITMP1);
+ M_INTMOVE(REG_ITMP2_XPTR, d);
+ emit_store(jd, NULL, var, d);
+ }
+ else {
+ assert((var->flags & INOUT));
}
+ }
#if defined(ENABLE_LSRA)
}
#endif
-
/* walk through all instructions */
len = bptr->icount;
}
MCODECHECK(64); /* an instruction usually needs < 64 words */
+
switch (iptr->opc) {
case ICMD_INLINE_START:
case ICMD_NOP: /* ... ==> ... */
break;
+
+ case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
+
+ s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+ emit_nullpointer_check(cd, iptr, s1);
+ break;
/* constant operations ************************************************/
case ICMD_FCONST: /* ... ==> ..., constant */
d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
- disp = dseg_addfloat(cd, iptr->sx.val.f);
+ disp = dseg_add_float(cd, iptr->sx.val.f);
M_FLD(d, REG_PV, disp);
emit_store_dst(jd, iptr, d);
break;
case ICMD_DCONST: /* ... ==> ..., constant */
d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
- disp = dseg_adddouble(cd, iptr->sx.val.d);
+ disp = dseg_add_double(cd, iptr->sx.val.d);
M_DLD(d, REG_PV, disp);
emit_store_dst(jd, iptr, d);
break;
d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
- disp = dseg_addaddress(cd, NULL);
+ cr = iptr->sx.val.c.ref;
+ disp = dseg_add_unique_address(cd, cr);
- codegen_addpatchref(cd, PATCHER_aconst,
- iptr->sx.val.c.ref,
- disp);
-
- if (opt_showdisassemble) {
- M_NOP; M_NOP;
- }
+ codegen_add_patch_ref(cd, PATCHER_aconst, cr, disp);
M_ALD(d, REG_PV, disp);
- } else {
+ }
+ else {
if (iptr->sx.val.anyptr == NULL) {
M_INTMOVE(REG_ZERO, d);
- } else {
- disp = dseg_addaddress(cd, iptr->sx.val.anyptr);
+ }
+ else {
+ disp = dseg_add_address(cd, iptr->sx.val.anyptr);
M_ALD(d, REG_PV, disp);
}
}
break;
- /* load/store operations **********************************************/
+ /* load/store/copy/move operations ************************************/
case ICMD_ILOAD: /* ... ==> ..., content of local variable */
- case ICMD_LLOAD: /* op1 = local variable */
- case ICMD_ALOAD:
-
- d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
- if ((iptr->dst.var->varkind == LOCALVAR) &&
- (iptr->dst.var->varnum == iptr->s1.localindex))
- break;
- var = &(rd->locals[iptr->s1.localindex][iptr->opc - ICMD_ILOAD]);
- if (var->flags & INMEMORY) {
- M_ALD(REG_SP, var->regoff * 8, d);
- } else {
- M_INTMOVE(var->regoff, d);
- }
- emit_store_dst(jd, iptr, d);
- break;
-
+ case ICMD_LLOAD: /* ... ==> ..., content of local variable */
+ case ICMD_ALOAD: /* ... ==> ..., content of local variable */
case ICMD_FLOAD: /* ... ==> ..., content of local variable */
- case ICMD_DLOAD: /* op1 = local variable */
-
- d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
- if ((iptr->dst.var->varkind == LOCALVAR) &&
- (iptr->dst.var->varnum == iptr->s1.localindex))
- break;
- var = &(rd->locals[iptr->s1.localindex][iptr->opc - ICMD_ILOAD]);
- if (var->flags & INMEMORY) {
- M_DLD(d, REG_SP, var->regoff * 8);
- } else {
- M_FLTMOVE(var->regoff, d);
- }
- emit_store_dst(jd, iptr, d);
- break;
-
-
+ case ICMD_DLOAD: /* ... ==> ..., content of local variable */
case ICMD_ISTORE: /* ..., value ==> ... */
- case ICMD_LSTORE: /* op1 = local variable */
- case ICMD_ASTORE:
-
- if ((iptr->s1.var->varkind == LOCALVAR) &&
- (iptr->s1.var->varnum == iptr->dst.localindex))
- break;
- var = &(rd->locals[iptr->dst.localindex][iptr->opc - ICMD_ISTORE]);
- if (var->flags & INMEMORY) {
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- M_STX(s1, REG_SP, var->regoff * 8);
- } else {
- s1 = emit_load_s1(jd, iptr, var->regoff);
- M_INTMOVE(s1, var->regoff);
- }
- break;
-
+ case ICMD_LSTORE: /* ..., value ==> ... */
case ICMD_FSTORE: /* ..., value ==> ... */
- case ICMD_DSTORE: /* op1 = local variable */
+ case ICMD_DSTORE: /* ..., value ==> ... */
+ case ICMD_COPY:
+ case ICMD_MOVE:
- if ((iptr->s1.var->varkind == LOCALVAR) &&
- (iptr->s1.var->varnum == iptr->dst.localindex))
- break;
- var = &(rd->locals[iptr->dst.localindex][iptr->opc - ICMD_ISTORE]);
- if (var->flags & INMEMORY) {
- s1 = emit_load_s1(jd, iptr, REG_FTMP1);
- M_DST(s1, REG_SP, var->regoff * 8);
- } else {
- s1 = emit_load_s1(jd, iptr, var->regoff);
- M_FLTMOVE(s1, var->regoff);
- }
+ emit_copy(jd, iptr, VAROP(iptr->s1), VAROP(iptr->dst));
break;
+ case ICMD_ASTORE:
+ if (!(iptr->flags.bits & INS_FLAG_RETADDR))
+ emit_copy(jd, iptr, VAROP(iptr->s1), VAROP(iptr->dst));
+ break;
+
/* pop/dup/swap operations ********************************************/
case ICMD_POP2: /* ..., value, value ==> ... */
break;
- case ICMD_DUP: /* ..., a ==> ..., a, a */
-
- M_COPY(iptr->s1.var, iptr->dst.var);
- break;
-
- case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
-
- M_COPY(iptr->dst.dupslots[ 1], iptr->dst.dupslots[2+2]);
- M_COPY(iptr->dst.dupslots[ 0], iptr->dst.dupslots[2+1]);
- M_COPY(iptr->dst.dupslots[2+2], iptr->dst.dupslots[2+0]);
- break;
-
- case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
-
- M_COPY(iptr->dst.dupslots[ 2], iptr->dst.dupslots[3+3]);
- M_COPY(iptr->dst.dupslots[ 1], iptr->dst.dupslots[3+2]);
- M_COPY(iptr->dst.dupslots[ 0], iptr->dst.dupslots[3+1]);
- M_COPY(iptr->dst.dupslots[3+3], iptr->dst.dupslots[3+0]);
- break;
-
- case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
-
- M_COPY(iptr->dst.dupslots[ 1], iptr->dst.dupslots[2+1]);
- M_COPY(iptr->dst.dupslots[ 0], iptr->dst.dupslots[2+0]);
- break;
-
- case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
-
- M_COPY(iptr->dst.dupslots[ 2], iptr->dst.dupslots[3+4]);
- M_COPY(iptr->dst.dupslots[ 1], iptr->dst.dupslots[3+3]);
- M_COPY(iptr->dst.dupslots[ 0], iptr->dst.dupslots[3+2]);
- M_COPY(iptr->dst.dupslots[3+4], iptr->dst.dupslots[3+1]);
- M_COPY(iptr->dst.dupslots[3+3], iptr->dst.dupslots[3+0]);
- break;
-
- case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
-
- M_COPY(iptr->dst.dupslots[ 3], iptr->dst.dupslots[4+5]);
- M_COPY(iptr->dst.dupslots[ 2], iptr->dst.dupslots[4+4]);
- M_COPY(iptr->dst.dupslots[ 1], iptr->dst.dupslots[4+3]);
- M_COPY(iptr->dst.dupslots[ 0], iptr->dst.dupslots[4+2]);
- M_COPY(iptr->dst.dupslots[4+5], iptr->dst.dupslots[4+1]);
- M_COPY(iptr->dst.dupslots[4+4], iptr->dst.dupslots[4+0]);
- break;
-
- case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
-
- M_COPY(iptr->dst.dupslots[ 1], iptr->dst.dupslots[2+0]);
- M_COPY(iptr->dst.dupslots[ 0], iptr->dst.dupslots[2+1]);
- break;
-
/* integer operations *************************************************/
break;
case ICMD_INT2CHAR: /* ..., value ==> ..., value */
- case ICMD_INT2SHORT:
+
+ s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+ d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+ M_SLLX_IMM(s1, 48, d);
+ M_SRLX_IMM( d, 48, d);
+ emit_store_dst(jd, iptr, d);
+ break;
+
+ case ICMD_INT2SHORT: /* ..., value ==> ..., value */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
emit_store_dst(jd, iptr, d);
break;
+ case ICMD_IINC:
case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
/* sx.val.i = constant */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
- gen_div_check(s2);
+ emit_arithmetic_check(cd, iptr, s2);
M_ISEXT(s1, s1);
/* XXX trim s2 like s1 ? */
M_DIVX(s1, s2, d);
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
- gen_div_check(s2);
+ emit_arithmetic_check(cd, iptr, s2);
M_DIVX(s1, s2, d);
emit_store_dst(jd, iptr, d);
break;
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
- gen_div_check(s2);
+ emit_arithmetic_check(cd, iptr, s2);
M_ISEXT(s1, s1);
/* XXX trim s2 like s1 ? */
- M_DIVX(s1, s2, d);
- M_MULX(s2, d, d);
- M_SUB(s1, d, d);
+ M_DIVX(s1, s2, REG_ITMP3);
+ M_MULX(s2, REG_ITMP3, REG_ITMP3);
+ M_SUB(s1, REG_ITMP3, d);
emit_store_dst(jd, iptr, d);
break;
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
- gen_div_check(s2);
- M_DIVX(s1, s2, d);
- M_MULX(s2, d, d);
- M_SUB(s1, d, d);
+ emit_arithmetic_check(cd, iptr, s2);
+ M_DIVX(s1, s2, REG_ITMP3);
+ M_MULX(s2, REG_ITMP3, REG_ITMP3);
+ M_SUB(s1, REG_ITMP3, d);
emit_store_dst(jd, iptr, d);
break;
break;
case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
- case ICMD_LSHL:
+
+ s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+ s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+ d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+ M_SLL(s1, s2, d);
+ emit_store_dst(jd, iptr, d);
+ break;
+
+ case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
break;
case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
- case ICMD_LSHLCONST: /* val.i = constant */
+ /* val.i = constant */
+
+ s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+ d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+ M_SLL_IMM(s1, iptr->sx.val.i, d);
+ emit_store_dst(jd, iptr, d);
+ break;
+
+ case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
+ /* val.i = constant */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
break;
- case ICMD_IINC: /* ..., value ==> ..., value + constant */
- /* s1.localindex = variable, sx.val.i = constant */
-
- var = &(rd->locals[iptr->s1.localindex][TYPE_INT]);
- if (var->flags & INMEMORY) {
- s1 = REG_ITMP1;
- M_LDX(s1, REG_SP, var->regoff * 8);
- } else
- s1 = var->regoff;
- if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
- M_ADD_IMM(s1, iptr->sx.val.i, s1);
- } else {
- ICONST(REG_ITMP2, iptr->sx.val.i);
- M_ADD(s1, REG_ITMP2, s1);
- }
- if (var->flags & INMEMORY)
- M_STX(s1, REG_SP, var->regoff * 8);
- break;
-
-
/* floating operations ************************************************/
case ICMD_FNEG: /* ..., value ==> ..., - value */
case ICMD_I2F:
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
- disp = dseg_addfloat(cd, 0.0);
+ disp = dseg_add_float(cd, 0.0);
M_IST (s1, REG_PV_CALLEE, disp);
M_FLD (d, REG_PV_CALLEE, disp);
M_CVTIF (d, d); /* rd gets translated to double target register */
case ICMD_I2D:
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
- disp = dseg_adddouble(cd, 0.0);
- M_STX (s1, REG_PV_CALLEE, disp);
- M_DLD (REG_FTMP2, REG_PV_CALLEE, disp); /* REG_FTMP2 needs to be a double temp */
- M_CVTLF (REG_FTMP2, d); /* rd gets translated to double target register */
+ disp = dseg_add_float(cd, 0.0);
+ M_IST (s1, REG_PV_CALLEE, disp);
+ M_FLD (REG_FTMP2, REG_PV_CALLEE, disp); /* REG_FTMP2 needs to be a double temp */
+ M_CVTID (REG_FTMP2, d); /* rd gets translated to double target register */
emit_store_dst(jd, iptr, d);
break;
case ICMD_F2I: /* ..., value ==> ..., (int) value */
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
- disp = dseg_addfloat(cd, 0.0);
+ disp = dseg_add_float(cd, 0.0);
M_CVTFI(s1, REG_FTMP2);
M_FST(REG_FTMP2, REG_PV_CALLEE, disp);
M_ILD(d, REG_PV, disp);
case ICMD_D2I: /* ..., value ==> ..., (int) value */
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
- disp = dseg_addfloat(cd, 0.0);
+ disp = dseg_add_float(cd, 0.0);
M_CVTDI(s1, REG_FTMP2);
M_FST(REG_FTMP2, REG_PV, disp);
M_ILD(d, REG_PV, disp);
case ICMD_F2L: /* ..., value ==> ..., (long) value */
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
- disp = dseg_adddouble(cd, 0.0);
+ disp = dseg_add_double(cd, 0.0);
M_CVTFL(s1, REG_FTMP2); /* FTMP2 needs to be double reg */
M_DST(REG_FTMP2, REG_PV, disp);
M_LDX(d, REG_PV, disp);
case ICMD_D2L: /* ..., value ==> ..., (long) value */
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
- disp = dseg_adddouble(cd, 0.0);
+ disp = dseg_add_double(cd, 0.0);
M_CVTDL(s1, REG_FTMP2); /* FTMP2 needs to be double reg */
M_DST(REG_FTMP2, REG_PV, disp);
M_LDX(d, REG_PV, disp);
s2 = emit_load_s2(jd, iptr, REG_FTMP2);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
M_FCMP(s1,s2);
- M_OR_IMM(REG_ZERO, -1, REG_ITMP3); /* less by default (less or unordered) */
- M_CMOVFEQ_IMM(0, REG_ITMP3); /* 0 if equal */
- M_CMOVFGT_IMM(1, REG_ITMP3); /* 1 if greater */
+ M_OR_IMM(REG_ZERO, -1, d); /* less by default (less or unordered) */
+ M_CMOVFEQ_IMM(0, d); /* 0 if equal */
+ M_CMOVFGT_IMM(1, d); /* 1 if greater */
emit_store_dst(jd, iptr, d);
break;
s2 = emit_load_s2(jd, iptr, REG_FTMP2);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
M_DCMP(s1,s2);
- M_OR_IMM(REG_ZERO, -1, REG_ITMP3); /* less by default (less or unordered) */
- M_CMOVFEQ_IMM(0, REG_ITMP3); /* 0 if equal */
- M_CMOVFGT_IMM(1, REG_ITMP3); /* 1 if greater */
+ M_OR_IMM(REG_ZERO, -1, d); /* less by default (less or unordered) */
+ M_CMOVFEQ_IMM(0, d); /* 0 if equal */
+ M_CMOVFGT_IMM(1, d); /* 1 if greater */
emit_store_dst(jd, iptr, d);
break;
s2 = emit_load_s2(jd, iptr, REG_FTMP2);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
M_FCMP(s1,s2);
- M_OR_IMM(REG_ZERO, 1, REG_ITMP3); /* greater by default (greater or unordered) */
- M_CMOVFEQ_IMM(0, REG_ITMP3); /* 0 if equal */
- M_CMOVFLT_IMM(-1, REG_ITMP3); /* -1 if less */
+ M_OR_IMM(REG_ZERO, 1, d); /* greater by default (greater or unordered) */
+ M_CMOVFEQ_IMM(0, d); /* 0 if equal */
+ M_CMOVFLT_IMM(-1, d); /* -1 if less */
emit_store_dst(jd, iptr, d);
break;
s2 = emit_load_s2(jd, iptr, REG_FTMP2);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
M_DCMP(s1,s2);
- M_OR_IMM(REG_ZERO, 1, REG_ITMP3); /* greater by default (greater or unordered) */
- M_CMOVFEQ_IMM(0, REG_ITMP3); /* 0 if equal */
- M_CMOVFLT_IMM(-1, REG_ITMP3); /* -1 if less */
+ M_OR_IMM(REG_ZERO, 1, d); /* greater by default (greater or unordered) */
+ M_CMOVFEQ_IMM(0, d); /* 0 if equal */
+ M_CMOVFLT_IMM(-1, d); /* -1 if less */
emit_store_dst(jd, iptr, d);
break;
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
- gen_nullptr_check(s1);
+ emit_nullpointer_check(cd, iptr, s1);
M_ILD(d, s1, OFFSET(java_arrayheader, size));
emit_store_dst(jd, iptr, d);
break;
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
- }
+ /* implicit null-pointer check */
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
M_AADD(s2, s1, REG_ITMP3);
- M_BLDS(d, REG_ITMP3, OFFSET(java_chararray, data[0]));
+ M_BLDS(d, REG_ITMP3, OFFSET(java_bytearray, data[0]));
emit_store_dst(jd, iptr, d);
break;
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
- }
+ /* implicit null-pointer check */
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
M_AADD(s2, s1, REG_ITMP3);
M_AADD(s2, REG_ITMP3, REG_ITMP3);
M_SLDU(d, REG_ITMP3, OFFSET(java_chararray, data[0]));
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
- }
+ /* implicit null-pointer check */
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
M_AADD(s2, s1, REG_ITMP3);
M_AADD(s2, REG_ITMP3, REG_ITMP3);
- M_SLDS(d, REG_ITMP3, OFFSET(java_chararray, data[0]));
+ M_SLDS(d, REG_ITMP3, OFFSET(java_shortarray, data[0]));
emit_store_dst(jd, iptr, d);
break;
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
- }
+ /* implicit null-pointer check */
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
M_ASLL_IMM(s2, 2, REG_ITMP3);
M_AADD(REG_ITMP3, s1, REG_ITMP3);
M_ILD(d, REG_ITMP3, OFFSET(java_intarray, data[0]));
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
- }
+ /* implicit null-pointer check */
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
M_ASLL_IMM(s2, 3, REG_ITMP3);
M_AADD(REG_ITMP3, s1, REG_ITMP3);
M_LDX(d, REG_ITMP3, OFFSET(java_longarray, data[0]));
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
- }
+ /* implicit null-pointer check */
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
M_ASLL_IMM(s2, 2, REG_ITMP3);
M_AADD(REG_ITMP3, s1, REG_ITMP3);
M_FLD(d, REG_ITMP3, OFFSET(java_floatarray, data[0]));
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
- }
+ /* implicit null-pointer check */
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
M_ASLL_IMM(s2, 3, REG_ITMP3);
M_AADD(REG_ITMP3, s1, REG_ITMP3);
M_DLD(d, REG_ITMP3, OFFSET(java_doublearray, data[0]));
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
- }
+ /* implicit null-pointer check */
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP3);
M_AADD(REG_ITMP3, s1, REG_ITMP3);
M_ALD(d, REG_ITMP3, OFFSET(java_objectarray, data[0]));
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
- }
+ /* implicit null-pointer check */
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
M_AADD(s2, s1, REG_ITMP1);
s3 = emit_load_s3(jd, iptr, REG_ITMP3);
M_BST(s3, REG_ITMP1, OFFSET(java_bytearray, data[0]));
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
- }
+ /* implicit null-pointer check */
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
M_AADD(s2, s1, REG_ITMP1);
M_AADD(s2, REG_ITMP1, REG_ITMP1);
s3 = emit_load_s3(jd, iptr, REG_ITMP3);
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
- }
+ /* implicit null-pointer check */
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
M_ASLL_IMM(s2, 2, REG_ITMP2);
M_AADD(REG_ITMP2, s1, REG_ITMP1);
s3 = emit_load_s3(jd, iptr, REG_ITMP3);
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
- }
+ /* implicit null-pointer check */
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
M_ASLL_IMM(s2, 3, REG_ITMP2);
M_AADD(REG_ITMP2, s1, REG_ITMP1);
s3 = emit_load_s3(jd, iptr, REG_ITMP3);
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
- }
+ /* implicit null-pointer check */
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
M_ASLL_IMM(s2, 2, REG_ITMP2);
M_AADD(REG_ITMP2, s1, REG_ITMP1);
s3 = emit_load_s3(jd, iptr, REG_FTMP1);
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
- }
+ /* implicit null-pointer check */
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
M_ASLL_IMM(s2, 3, REG_ITMP2);
M_AADD(REG_ITMP2, s1, REG_ITMP1);
s3 = emit_load_s3(jd, iptr, REG_FTMP1);
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
- }
+ /* implicit null-pointer check */
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
s3 = emit_load_s3(jd, iptr, REG_ITMP3);
M_MOV(s1, rd->argintregs[0]);
M_MOV(s3, rd->argintregs[1]);
- disp = dseg_addaddress(cd, BUILTIN_canstore);
+ disp = dseg_add_functionptr(cd, BUILTIN_canstore);
M_ALD(REG_ITMP3, REG_PV, disp);
M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
M_NOP;
-
- M_BEQZ(REG_RESULT_CALLER, 0);
- codegen_add_arraystoreexception_ref(cd);
- M_NOP;
+ emit_exception_check(cd, iptr);
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
M_AADD(REG_ITMP2, s1, REG_ITMP1);
s3 = emit_load_s3(jd, iptr, REG_ITMP3);
+ /* implicit null-pointer check */
M_AST_INTERN(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
break;
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
- }
+ /* implicit null-pointer check */
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
M_AADD(s2, s1, REG_ITMP1);
M_BST(REG_ZERO, REG_ITMP1, OFFSET(java_bytearray, data[0]));
break;
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
- }
+ /* implicit null-pointer check */
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
M_AADD(s2, s1, REG_ITMP1);
M_AADD(s2, REG_ITMP1, REG_ITMP1);
M_SST(REG_ZERO, REG_ITMP1, OFFSET(java_chararray, data[0]));
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
- }
+ /* implicit null-pointer check */
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
M_ASLL_IMM(s2, 2, REG_ITMP2);
M_AADD(REG_ITMP2, s1, REG_ITMP1);
M_IST_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_intarray, data[0]));
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
- }
+ /* implicit null-pointer check */
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
M_ASLL_IMM(s2, 3, REG_ITMP2);
M_AADD(REG_ITMP2, s1, REG_ITMP1);
M_STX_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_longarray, data[0]));
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
- }
+ /* implicit null-pointer check */
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
M_AADD(REG_ITMP2, s1, REG_ITMP1);
M_AST_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_objectarray, data[0]));
case ICMD_GETSTATIC: /* ... ==> ..., value */
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
- unresolved_field *uf = iptr->sx.s23.s3.uf;
-
+ uf = iptr->sx.s23.s3.uf;
fieldtype = uf->fieldref->parseddesc.fd->type;
+ disp = dseg_add_unique_address(cd, uf);
- disp = dseg_addaddress(cd, NULL);
-
- codegen_addpatchref(cd, PATCHER_get_putstatic, uf, disp);
-
- if (opt_showdisassemble) {
- M_NOP; M_NOP;
- }
-
- } else {
- fieldinfo *fi = iptr->sx.s23.s3.fmiref->p.field;
-
- disp = dseg_addaddress(cd, &(fi->value));
-
- if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
- codegen_addpatchref(cd, PATCHER_clinit, fi->class, 0);
+ codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
+ }
+ else {
+ fi = iptr->sx.s23.s3.fmiref->p.field;
+ fieldtype = fi->type;
+ disp = dseg_add_address(cd, &(fi->value));
- if (opt_showdisassemble) {
- M_NOP; M_NOP;
- }
- }
+ if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
+ codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, disp);
}
M_ALD(REG_ITMP1, REG_PV, disp);
+
switch (fieldtype) {
case TYPE_INT:
d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
M_ILD_INTERN(d, REG_ITMP1, 0);
- emit_store_dst(jd, iptr, d);
break;
case TYPE_LNG:
d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
M_LDX_INTERN(d, REG_ITMP1, 0);
- emit_store_dst(jd, iptr, d);
break;
case TYPE_ADR:
d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
M_ALD_INTERN(d, REG_ITMP1, 0);
- emit_store_dst(jd, iptr, d);
break;
case TYPE_FLT:
d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
M_FLD_INTERN(d, REG_ITMP1, 0);
- emit_store_dst(jd, iptr, d);
break;
case TYPE_DBL:
d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
M_DLD_INTERN(d, REG_ITMP1, 0);
- emit_store_dst(jd, iptr, d);
break;
}
+ emit_store_dst(jd, iptr, d);
break;
case ICMD_PUTSTATIC: /* ..., value ==> ... */
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
- unresolved_field *uf = iptr->sx.s23.s3.uf;
-
+ uf = iptr->sx.s23.s3.uf;
fieldtype = uf->fieldref->parseddesc.fd->type;
+ disp = dseg_add_unique_address(cd, uf);
- disp = dseg_addaddress(cd, NULL);
-
- codegen_addpatchref(cd, PATCHER_get_putstatic,
- iptr->sx.s23.s3.uf, disp);
-
- if (opt_showdisassemble) {
- M_NOP; M_NOP;
- }
-
- } else {
- fieldinfo *fi = iptr->sx.s23.s3.fmiref->p.field;
-
- disp = dseg_addaddress(cd, &(fi->value));
-
- if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
- codegen_addpatchref(cd, PATCHER_clinit, fi->class, 0);
+ codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
+ }
+ else {
+ fi = iptr->sx.s23.s3.fmiref->p.field;
+ fieldtype = fi->type;
+ disp = dseg_add_address(cd, &(fi->value));
- if (opt_showdisassemble) {
- M_NOP; M_NOP;
- }
- }
+ if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
+ codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, disp);
}
M_ALD(REG_ITMP1, REG_PV, disp);
+
switch (fieldtype) {
case TYPE_INT:
- s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- M_IST_INTERN(s2, REG_ITMP1, 0);
+ s1 = emit_load_s1(jd, iptr, REG_ITMP2);
+ M_IST_INTERN(s1, REG_ITMP1, 0);
break;
case TYPE_LNG:
- s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- M_STX_INTERN(s2, REG_ITMP1, 0);
+ s1 = emit_load_s1(jd, iptr, REG_ITMP2);
+ M_STX_INTERN(s1, REG_ITMP1, 0);
break;
case TYPE_ADR:
- s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- M_AST_INTERN(s2, REG_ITMP1, 0);
+ s1 = emit_load_s1(jd, iptr, REG_ITMP2);
+ M_AST_INTERN(s1, REG_ITMP1, 0);
break;
case TYPE_FLT:
- s2 = emit_load_s2(jd, iptr, REG_FTMP2);
- M_FST_INTERN(s2, REG_ITMP1, 0);
+ s1 = emit_load_s1(jd, iptr, REG_FTMP2);
+ M_FST_INTERN(s1, REG_ITMP1, 0);
break;
case TYPE_DBL:
- s2 = emit_load_s2(jd, iptr, REG_FTMP2);
- M_DST_INTERN(s2, REG_ITMP1, 0);
+ s1 = emit_load_s1(jd, iptr, REG_FTMP2);
+ M_DST_INTERN(s1, REG_ITMP1, 0);
break;
}
break;
/* following NOP) */
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
- unresolved_field *uf = iptr->sx.s23.s3.uf;
-
+ uf = iptr->sx.s23.s3.uf;
fieldtype = uf->fieldref->parseddesc.fd->type;
+ disp = dseg_add_unique_address(cd, uf);
- disp = dseg_addaddress(cd, NULL);
-
- codegen_addpatchref(cd, PATCHER_get_putstatic,
- uf, disp);
-
- if (opt_showdisassemble) {
- M_NOP; M_NOP;
- }
-
- } else {
- fieldinfo *fi = iptr->sx.s23.s3.fmiref->p.field;
-
+ codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
+ }
+ else {
+ fi = iptr->sx.s23.s3.fmiref->p.field;
fieldtype = fi->type;
+ disp = dseg_add_address(cd, &(fi->value));
-
- disp = dseg_addaddress(cd, &(fi->value));
-
- if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
- codegen_addpatchref(cd, PATCHER_clinit, fi->class, 0);
-
- if (opt_showdisassemble) {
- M_NOP; M_NOP;
- }
- }
+ if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
+ codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, disp);
}
M_ALD(REG_ITMP1, REG_PV, disp);
+
switch (fieldtype) {
case TYPE_INT:
M_IST_INTERN(REG_ZERO, REG_ITMP1, 0);
case ICMD_GETFIELD: /* ... ==> ..., value */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- gen_nullptr_check(s1);
+ emit_nullpointer_check(cd, iptr, s1);
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
- unresolved_field *uf = iptr->sx.s23.s3.uf;
+ uf = iptr->sx.s23.s3.uf;
fieldtype = uf->fieldref->parseddesc.fd->type;
+ disp = 0;
- codegen_addpatchref(cd, PATCHER_get_putfield,
- iptr->sx.s23.s3.uf, 0);
-
- if (opt_showdisassemble) {
- M_NOP; M_NOP;
- }
-
- disp = 0;
-
- } else {
- disp = iptr->sx.s23.s3.fmiref->p.field->offset;
+ codegen_add_patch_ref(cd, PATCHER_get_putfield, uf, 0);
+ }
+ else {
+ fi = iptr->sx.s23.s3.fmiref->p.field;
+ fieldtype = fi->type;
+ disp = fi->offset;
}
switch (fieldtype) {
case TYPE_INT:
d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
M_ILD(d, s1, disp);
- emit_store_dst(jd, iptr, d);
break;
case TYPE_LNG:
d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
M_LDX(d, s1, disp);
- emit_store_dst(jd, iptr, d);
break;
case TYPE_ADR:
d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
M_ALD(d, s1, disp);
- emit_store_dst(jd, iptr, d);
break;
case TYPE_FLT:
d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
M_FLD(d, s1, disp);
- emit_store_dst(jd, iptr, d);
break;
case TYPE_DBL:
d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
M_DLD(d, s1, disp);
- emit_store_dst(jd, iptr, d);
+ break;
+ default:
+ assert(0);
break;
}
+ emit_store_dst(jd, iptr, d);
break;
case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
- s1 = emit_load_s1(jd, iptr, REG_ITMP2);
- gen_nullptr_check(s1);
-
- /*if (!IS_FLT_DBL_TYPE(fieldtype)) {
- s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- } else {*/
- s2 = emit_load_s2(jd, iptr, REG_IFTMP);
- /*}*/
+ s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+ emit_nullpointer_check(cd, iptr, s1);
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
- unresolved_field *uf = iptr->sx.s23.s3.uf;
-
+ uf = iptr->sx.s23.s3.uf;
fieldtype = uf->fieldref->parseddesc.fd->type;
-
- codegen_addpatchref(cd, PATCHER_get_putfield,
- iptr->sx.s23.s3.uf, 0);
-
- if (opt_showdisassemble) {
- M_NOP; M_NOP;
+ disp = 0;
+ }
+ else {
+ uf = NULL;
+ fi = iptr->sx.s23.s3.fmiref->p.field;
+ fieldtype = fi->type;
+ disp = fi->offset;
}
- disp = 0;
+ if (IS_INT_LNG_TYPE(fieldtype))
+ s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+ else
+ s2 = emit_load_s2(jd, iptr, REG_FTMP2);
- } else {
- disp = iptr->sx.s23.s3.fmiref->p.field->offset;
- }
+ if (INSTRUCTION_IS_UNRESOLVED(iptr))
+ codegen_add_patch_ref(cd, PATCHER_get_putfield, uf, 0);
switch (fieldtype) {
case TYPE_INT:
case TYPE_DBL:
M_DST(s2, s1, disp);
break;
+ default:
+ assert(0);
+ break;
}
break;
/* following NOP) */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- gen_nullptr_check(s1);
+ emit_nullpointer_check(cd, iptr, s1);
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
unresolved_field *uf = iptr->sx.s23.s3.uf;
#ifdef ENABLE_VERIFIER
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
- codegen_addpatchref(cd, PATCHER_athrow_areturn,
- iptr->sx.s23.s2.uc, 0);
+ unresolved_class *uc = iptr->sx.s23.s2.uc;
- if (opt_showdisassemble)
- M_NOP;
+ codegen_add_patch_ref(cd, PATCHER_athrow_areturn, uc, 0);
}
#endif /* ENABLE_VERIFIER */
- disp = dseg_addaddress(cd, asm_handle_exception);
- M_ALD(REG_ITMP2, REG_PV, disp);
- M_JMP(REG_ITMP3_XPC, REG_ITMP2, REG_ZERO);
+ disp = dseg_add_functionptr(cd, asm_handle_exception);
+ M_ALD(REG_ITMP1, REG_PV, disp);
+ M_JMP(REG_ITMP3_XPC, REG_ITMP1, REG_ZERO);
M_NOP;
M_NOP; /* nop ensures that XPC is less than the end */
/* of basic block */
break;
case ICMD_GOTO: /* ... ==> ... */
- M_BR(0);
- codegen_addreference(cd, iptr->dst.block);
- M_NOP;
+ case ICMD_RET: /* ... ==> ... */
+
+ emit_br(cd, iptr->dst.block);
ALIGNCODENOP;
break;
case ICMD_JSR: /* ... ==> ... */
- dseg_addtarget(cd, iptr->sx.s23.s3.jsrtarget.block);
- M_ALD(REG_ITMP1, REG_PV, -(cd->dseglen));
- M_JMP(REG_ITMP1, REG_ITMP1, REG_ZERO); /* REG_ITMP1 = return address */
- M_NOP;
- break;
-
- case ICMD_RET: /* ... ==> ... */
- /* s1.localindex = local variable */
- var = &(rd->locals[iptr->s1.localindex][TYPE_ADR]);
- if (var->flags & INMEMORY) {
- M_ALD(REG_ITMP1, REG_SP, var->regoff * 8);
- M_RET(REG_ITMP1);
- } else
- M_RET(var->regoff);
- M_NOP;
+ emit_br(cd, iptr->sx.s23.s3.jsrtarget.block);
ALIGNCODENOP;
break;
case ICMD_IFNULL: /* ..., value ==> ... */
+ case ICMD_IFNONNULL:
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- M_BEQZ(s1, 0);
- codegen_addreference(cd, iptr->dst.block);
- M_NOP;
- break;
-
- case ICMD_IFNONNULL: /* ..., value ==> ... */
-
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- M_BNEZ(s1, 0);
- codegen_addreference(cd, iptr->dst.block);
- M_NOP;
+ emit_bccz(cd, iptr->dst.block, iptr->opc - ICMD_IFNULL, s1, BRANCH_OPT_NONE);
break;
+
+ /* Note: int compares must not branch on the register directly. */
+ /* Reason is, that register content is not 32-bit clean. */
case ICMD_IFEQ: /* ..., value ==> ... */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- if (iptr->sx.val.i == 0) {
- M_BEQZ(s1, 0);
- } else {
- if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
- M_CMP_IMM(s1, iptr->sx.val.i);
- }
- else {
- ICONST(REG_ITMP2, iptr->sx.val.i);
- M_CMP(s1, REG_ITMP2);
- }
- M_BEQ(0);
- }
- codegen_addreference(cd, iptr->dst.block);
- M_NOP;
+
+ if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
+ M_CMP_IMM(s1, iptr->sx.val.i);
+ }
+ else {
+ ICONST(REG_ITMP2, iptr->sx.val.i);
+ M_CMP(s1, REG_ITMP2);
+ }
+ emit_beq(cd, iptr->dst.block);
break;
case ICMD_IFLT: /* ..., value ==> ... */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- if (iptr->sx.val.i == 0) {
- M_BLTZ(s1, 0);
- } else {
- if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
- M_CMP_IMM(s1, iptr->sx.val.i);
- } else {
- ICONST(REG_ITMP2, iptr->sx.val.i);
- M_CMP(s1, REG_ITMP2);
- }
- M_BLT(0);
+
+ if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
+ M_CMP_IMM(s1, iptr->sx.val.i);
+ }
+ else {
+ ICONST(REG_ITMP2, iptr->sx.val.i);
+ M_CMP(s1, REG_ITMP2);
}
- codegen_addreference(cd, iptr->dst.block);
- M_NOP;
+ emit_blt(cd, iptr->dst.block);
break;
case ICMD_IFLE: /* ..., value ==> ... */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- if (iptr->sx.val.i == 0) {
- M_BLEZ(s1, 0);
- }
+
+ if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
+ M_CMP_IMM(s1, iptr->sx.val.i);
+ }
else {
- if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
- M_CMP_IMM(s1, iptr->sx.val.i);
- }
- else {
- ICONST(REG_ITMP2, iptr->sx.val.i);
- M_CMP(s1, REG_ITMP2);
- }
- M_BLE(0);
+ ICONST(REG_ITMP2, iptr->sx.val.i);
+ M_CMP(s1, REG_ITMP2);
}
- codegen_addreference(cd, iptr->dst.block);
- M_NOP;
+ emit_ble(cd, iptr->dst.block);
break;
case ICMD_IFNE: /* ..., value ==> ... */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- if (iptr->sx.val.i == 0) {
- M_BNEZ(s1, 0);
- }
+
+ if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
+ M_CMP_IMM(s1, iptr->sx.val.i);
+ }
else {
- if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
- M_CMP_IMM(s1, iptr->sx.val.i);
- }
- else {
- ICONST(REG_ITMP2, iptr->sx.val.i);
- M_CMP(s1, REG_ITMP2);
- }
- M_BNE(0);
+ ICONST(REG_ITMP2, iptr->sx.val.i);
+ M_CMP(s1, REG_ITMP2);
}
- codegen_addreference(cd, iptr->dst.block);
- M_NOP;
+ emit_bne(cd, iptr->dst.block);
break;
case ICMD_IFGT: /* ..., value ==> ... */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- if (iptr->sx.val.i == 0) {
- M_BLTZ(s1, 0);
- } else {
- if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
- M_CMP_IMM(s1, iptr->sx.val.i);
- } else {
- ICONST(REG_ITMP2, iptr->sx.val.i);
- M_CMP(s1, REG_ITMP2);
- }
- M_BGT(0);
+
+ if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
+ M_CMP_IMM(s1, iptr->sx.val.i);
+ }
+ else {
+ ICONST(REG_ITMP2, iptr->sx.val.i);
+ M_CMP(s1, REG_ITMP2);
}
- codegen_addreference(cd, iptr->dst.block);
- M_NOP;
+ emit_bgt(cd, iptr->dst.block);
break;
case ICMD_IFGE: /* ..., value ==> ... */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- if (iptr->sx.val.i == 0) {
- M_BLEZ(s1, 0);
- }
+
+ if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
+ M_CMP_IMM(s1, iptr->sx.val.i);
+ }
else {
- if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
- M_CMP_IMM(s1, iptr->sx.val.i);
- }
- else {
- ICONST(REG_ITMP2, iptr->sx.val.i);
- M_CMP(s1, REG_ITMP2);
- }
- M_BGE(0);
+ ICONST(REG_ITMP2, iptr->sx.val.i);
+ M_CMP(s1, REG_ITMP2);
}
- codegen_addreference(cd, iptr->dst.block);
- M_NOP;
+ emit_bge(cd, iptr->dst.block);
break;
case ICMD_IF_LEQ: /* ..., value ==> ... */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- if (iptr->sx.val.l == 0) {
- M_BEQZ(s1, 0);
- }
+ if (iptr->sx.val.l == 0)
+ emit_beqz(cd, iptr->dst.block, s1);
else {
if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
M_CMP_IMM(s1, iptr->sx.val.l);
LCONST(REG_ITMP2, iptr->sx.val.l);
M_CMP(s1, REG_ITMP2);
}
- M_XBEQ(0);
+ emit_beq_xcc(cd, iptr->dst.block);
}
- codegen_addreference(cd, iptr->dst.block);
- M_NOP;
break;
case ICMD_IF_LLT: /* ..., value ==> ... */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- if (iptr->sx.val.l == 0) {
- M_BLTZ(s1, 0);
- } else {
+ if (iptr->sx.val.l == 0)
+ emit_bltz(cd, iptr->dst.block, s1);
+ else {
if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
M_CMP_IMM(s1, iptr->sx.val.l);
- } else {
+ }
+ else {
ICONST(REG_ITMP2, iptr->sx.val.l);
M_CMP(s1, REG_ITMP2);
}
- M_XBLT(0);
+ emit_blt_xcc(cd, iptr->dst.block);
}
- codegen_addreference(cd, iptr->dst.block);
- M_NOP;
break;
case ICMD_IF_LLE: /* ..., value ==> ... */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- if (iptr->sx.val.l == 0) {
- M_BLEZ(s1, 0);
- }
+ if (iptr->sx.val.l == 0)
+ emit_blez(cd, iptr->dst.block, s1);
else {
if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
M_CMP_IMM(s1, iptr->sx.val.l);
- }
+ }
else {
ICONST(REG_ITMP2, iptr->sx.val.l);
M_CMP(s1, REG_ITMP2);
}
- M_XBLE(0);
+ emit_ble_xcc(cd, iptr->dst.block);
}
- codegen_addreference(cd, iptr->dst.block);
- M_NOP;
break;
case ICMD_IF_LNE: /* ..., value ==> ... */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- if (iptr->sx.val.l == 0) {
- M_BNEZ(s1, 0);
- }
+ if (iptr->sx.val.l == 0)
+ emit_bnez(cd, iptr->dst.block, s1);
else {
if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
- M_CMP_IMM(s1, iptr->sx.val.i);
+ M_CMP_IMM(s1, iptr->sx.val.l);
}
else {
ICONST(REG_ITMP2, iptr->sx.val.l);
M_CMP(s1, REG_ITMP2);
}
- M_XBNE(0);
+ emit_bne_xcc(cd, iptr->dst.block);
}
- codegen_addreference(cd, iptr->dst.block);
- M_NOP;
break;
case ICMD_IF_LGT: /* ..., value ==> ... */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- if (iptr->sx.val.l == 0) {
- M_BLTZ(s1, 0);
- } else {
+ if (iptr->sx.val.l == 0)
+ emit_bgtz(cd, iptr->dst.block, s1);
+ else {
if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
M_CMP_IMM(s1, iptr->sx.val.l);
- } else {
+ }
+ else {
ICONST(REG_ITMP2, iptr->sx.val.l);
M_CMP(s1, REG_ITMP2);
}
- M_XBGT(0);
+ emit_bgt_xcc(cd, iptr->dst.block);
}
- codegen_addreference(cd, iptr->dst.block);
- M_NOP;
break;
case ICMD_IF_LGE: /* ..., value ==> ... */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- if (iptr->sx.val.l == 0) {
- M_BLEZ(s1, 0);
- }
+ if (iptr->sx.val.l == 0)
+ emit_bgez(cd, iptr->dst.block, s1);
else {
if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
M_CMP_IMM(s1, iptr->sx.val.l);
- }
+ }
else {
ICONST(REG_ITMP2, iptr->sx.val.l);
M_CMP(s1, REG_ITMP2);
}
- M_XBGE(0);
+ emit_bge_xcc(cd, iptr->dst.block);
}
- codegen_addreference(cd, iptr->dst.block);
- M_NOP;
break;
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
M_CMP(s1, s2);
- M_XBEQ(0);
- codegen_addreference(cd, iptr->dst.block);
- M_NOP;
+ emit_beq_xcc(cd, iptr->dst.block);
break;
case ICMD_IF_ICMPEQ: /* 32-bit compare */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
M_CMP(s1, s2);
- M_BEQ(0);
- codegen_addreference(cd, iptr->dst.block);
- M_NOP;
+ emit_beq(cd, iptr->dst.block);
break;
case ICMD_IF_ACMPNE: /* ..., value, value ==> ... */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
M_CMP(s1, s2);
- M_XBNE(0);
- codegen_addreference(cd, iptr->dst.block);
- M_NOP;
+ emit_bne_xcc(cd, iptr->dst.block);
break;
case ICMD_IF_ICMPNE: /* 32-bit compare */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
M_CMP(s1, s2);
- M_BNE(0);
- codegen_addreference(cd, iptr->dst.block);
- M_NOP;
+ emit_bne(cd, iptr->dst.block);
break;
case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
M_CMP(s1, s2);
- M_XBLT(0);
- codegen_addreference(cd, iptr->dst.block);
- M_NOP;
+ emit_blt_xcc(cd, iptr->dst.block);
break;
case ICMD_IF_ICMPLT: /* 32-bit compare */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
M_CMP(s1, s2);
- M_BLT(0);
- codegen_addreference(cd, iptr->dst.block);
- M_NOP;
+ emit_blt(cd, iptr->dst.block);
break;
case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
M_CMP(s1, s2);
- M_XBGT(0);
- codegen_addreference(cd, iptr->dst.block);
- M_NOP;
+ emit_bgt_xcc(cd, iptr->dst.block);
break;
case ICMD_IF_ICMPGT: /* 32-bit compare */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
M_CMP(s1, s2);
- M_BGT(0);
- codegen_addreference(cd, iptr->dst.block);
- M_NOP;
+ emit_bgt(cd, iptr->dst.block);
break;
case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
M_CMP(s1, s2);
- M_BLE(0);
- codegen_addreference(cd, iptr->dst.block);
- M_NOP;
+ emit_ble_xcc(cd, iptr->dst.block);
break;
case ICMD_IF_ICMPLE: /* 32-bit compare */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
M_CMP(s1, s2);
- M_BLE(0);
- codegen_addreference(cd, iptr->dst.block);
- M_NOP;
+ emit_ble(cd, iptr->dst.block);
break;
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
M_CMP(s1, s2);
- M_BGE(0);
- codegen_addreference(cd, iptr->dst.block);
- M_NOP;
+ emit_bge_xcc(cd, iptr->dst.block);
break;
case ICMD_IF_ICMPGE: /* 32-bit compare */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
M_CMP(s1, s2);
- M_BGE(0);
- codegen_addreference(cd, iptr->dst.block);
- M_NOP;
+ emit_bge(cd, iptr->dst.block);
break;
#ifdef ENABLE_VERIFIER
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
- codegen_addpatchref(cd, PATCHER_athrow_areturn,
- iptr->sx.s23.s2.uc, 0);
+ unresolved_class *uc = iptr->sx.s23.s2.uc;
- if (opt_showdisassemble)
- M_NOP;
+ codegen_add_patch_ref(cd, PATCHER_athrow_areturn, uc, 0);
}
#endif /* ENABLE_VERIFIER */
goto nowperformreturn;
case ICMD_DRETURN:
s1 = emit_load_s1(jd, iptr, REG_FRESULT);
- M_FLTMOVE(s1, REG_FRESULT);
+ M_DBLMOVE(s1, REG_FRESULT);
goto nowperformreturn;
case ICMD_RETURN: /* ... ==> ... */
{
s4 i, p;
- p = stackframesize;
-
- /* call trace function */
+ p = cd->stackframesize;
#if !defined(NDEBUG)
- if (opt_verbosecall) {
- M_LDA(REG_SP, REG_SP, -3 * 8);
- M_AST(REG_RA_CALLEE, REG_SP, 0 * 8); /* XXX: no need to save anything but FRES ? */
- /* M_STX(REG_RESULT, REG_SP, 1 * 8); */
- M_DST(REG_FRESULT, REG_SP, 2 * 8);
-
- disp = dseg_addaddress(cd, m);
- M_ALD(rd->argintregs[0], REG_PV, disp);
- M_MOV(REG_RESULT_CALLEE, rd->argintregs[1]);
- M_FLTMOVE(REG_FRESULT, rd->argfltregs[2]);
- M_FLTMOVE(REG_FRESULT, rd->argfltregs[3]);
-
- disp = dseg_addaddress(cd, (void *) builtin_displaymethodstop);
- M_ALD(REG_ITMP3, REG_PV, disp);
- M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
- M_NOP;
-
- M_DLD(REG_FRESULT, REG_SP, 2 * 8);
- /* M_LDX(REG_RESULT, REG_SP, 1 * 8); */
- M_ALD(REG_RA_CALLEE, REG_SP, 0 * 8);
- M_LDA(REG_SP, REG_SP, 3 * 8);
- }
+ if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
+ emit_verbosecall_exit(jd);
#endif
#if defined(ENABLE_THREADS)
break;
}
- disp = dseg_addaddress(cd, BUILTIN_monitorexit);
+ disp = dseg_add_functionptr(cd, BUILTIN_monitorexit);
M_ALD(REG_ITMP3, REG_PV, disp);
M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO); /*REG_RA_CALLER */
- M_RETURN(REG_RA_CALLEE); /* implicit window restore */
+ M_RETURN(REG_RA_CALLEE, 8); /* implicit window restore */
M_NOP;
ALIGNCODENOP;
}
/* range check */
if (i <= 4095) {
- M_CMP_IMM(REG_ITMP1, i);
+ M_CMP_IMM(REG_ITMP1, i - 1);
}
else {
- ICONST(REG_ITMP2, i);
+ ICONST(REG_ITMP2, i - 1);
M_CMP(REG_ITMP1, REG_ITMP2);
}
- M_XBULT(0);
- codegen_addreference(cd, table[0].block); /* default target */
- M_ASLL_IMM(REG_ITMP1, POINTERSHIFT, REG_ITMP1); /* delay slot*/
+ emit_bugt(cd, table[0].block); /* default target */
/* build jump table top down and use address of lowest entry */
/* length of dataseg after last dseg_addtarget is used by load */
+ M_ASLL_IMM(REG_ITMP1, POINTERSHIFT, REG_ITMP1);
M_AADD(REG_ITMP1, REG_PV, REG_ITMP2);
M_ALD(REG_ITMP2, REG_ITMP2, -(cd->dseglen));
M_JMP(REG_ZERO, REG_ITMP2, REG_ZERO);
ICONST(REG_ITMP2, lookup->value);
M_CMP(s1, REG_ITMP2);
}
- M_BEQ(0);
- codegen_addreference(cd, lookup->target.block);
- M_NOP;
+ emit_beq(cd, lookup->target.block);
++lookup;
}
- M_BR(0);
- codegen_addreference(cd, iptr->sx.s23.s3.lookupdefault.block);
- M_NOP;
+ emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
ALIGNCODENOP;
break;
}
bte = iptr->sx.s23.s3.bte;
md = bte->md;
+
+ /* XXX: proper builtin calling and float args are so not implemented */
+ assert(md->paramcount <= 5 && md->argfltreguse < 1);
+
goto gen_method;
case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
/* copy arguments to registers or stack location */
- for (s3 = s3 - 1; s3 >= 0; s3--, src = src->prev) {
- if (src->varkind == ARGVAR)
+ for (s3 = s3 - 1; s3 >= 0; s3--) {
+ var = VAR(iptr->sx.s23.s2.args[s3]);
+
+ if (var->flags & PREALLOC)
continue;
- if (IS_INT_LNG_TYPE(src->type)) {
+
+ if (IS_INT_LNG_TYPE(var->type)) {
if (!md->params[s3].inmemory) {
s1 = rd->argintregs[md->params[s3].regoff];
- d = emit_load_s1(jd, iptr, s1);
+ d = emit_load(jd, iptr, var, s1);
M_INTMOVE(d, s1);
- } else {
- d = emit_load_s1(jd, iptr, REG_ITMP1);
- M_STX(d, REG_SP, md->params[s3].regoff * 8);
+ }
+ else {
+ d = emit_load(jd, iptr, var, REG_ITMP1);
+ M_STX(d, REG_SP, JITSTACK + md->params[s3].regoff * 8);
}
-
- } else {
+ }
+ else {
if (!md->params[s3].inmemory) {
s1 = rd->argfltregs[md->params[s3].regoff];
- d = emit_load_s1(jd, iptr, s1);
- if (IS_2_WORD_TYPE(src->type))
+ d = emit_load(jd, iptr, var, s1);
+ if (IS_2_WORD_TYPE(var->type))
M_DMOV(d, s1);
else
M_FMOV(d, s1);
-
- } else {
- d = emit_load_s1(jd, iptr, REG_FTMP1);
- if (IS_2_WORD_TYPE(src->type))
- M_DST(d, REG_SP, md->params[s3].regoff * 8);
+ }
+ else {
+ d = emit_load(jd, iptr, var, REG_FTMP1);
+ if (IS_2_WORD_TYPE(var->type))
+ M_DST(d, REG_SP, JITSTACK + md->params[s3].regoff * 8);
else
- M_FST(d, REG_SP, md->params[s3].regoff * 8);
+ M_FST(d, REG_SP, JITSTACK + md->params[s3].regoff * 8);
}
}
}
switch (iptr->opc) {
case ICMD_BUILTIN:
- /* XXX needs manual attention! */
- disp = dseg_addaddress(cd, bte->fp);
- d = md->returntype.type;
+ disp = dseg_add_functionptr(cd, bte->fp);
- M_ALD(REG_ITMP3, REG_PV, disp); /* built-in-function pointer */
- M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
- M_NOP;
-/* XXX: how do builtins handle the register window? */
-/* disp = (s4) (cd->mcodeptr - cd->mcodebase);*/
-/* M_LDA(REG_PV, REG_RA, -disp);*/
+ M_ALD(REG_PV_CALLER, REG_PV, disp); /* built-in-function pointer */
+ /* XXX jit-c-call */
+ /* generate the actual call */
+
+ M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
+ M_NOP;
+ disp = (s4) (cd->mcodeptr - cd->mcodebase);
+ /* REG_RA holds the value of the jmp instruction, therefore +8 */
+ M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- M_BEQZ(REG_RESULT_CALLER, 0);
- codegen_add_fillinstacktrace_ref(cd);
- M_NOP;
- }
+ emit_exception_check(cd, iptr);
break;
case ICMD_INVOKESPECIAL:
- M_BEQZ(REG_A0, 0);
- codegen_add_nullpointerexception_ref(cd);
- M_NOP;
- /* fall through */
+ emit_nullpointer_check(cd, iptr, REG_OUT0);
+ /* fall-through */
case ICMD_INVOKESTATIC:
- /* XXX needs manual attention! */
if (lm == NULL) {
- disp = dseg_addaddress(cd, NULL);
+ disp = dseg_add_unique_address(cd, NULL);
- codegen_addpatchref(cd, PATCHER_invokestatic_special,
+ codegen_add_patch_ref(cd, PATCHER_invokestatic_special,
um, disp);
-
- if (opt_showdisassemble) {
- M_NOP; M_NOP;
- }
}
else
- disp = dseg_addaddress(cd, lm->stubroutine);
-
- M_ALD(REG_PV_CALLER, REG_PV, disp); /* method pointer in callee pv */
- M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
- M_NOP;
-/* XXX no need to restore PV, when its in the regs */
+ disp = dseg_add_address(cd, lm->stubroutine);
+
+ M_ALD(REG_PV_CALLER, REG_PV, disp); /* method pointer in pv */
+
+ /* generate the actual call */
+
+ M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
+ M_NOP;
+ disp = (s4) (cd->mcodeptr - cd->mcodebase);
+ /* REG_RA holds the value of the jmp instruction, therefore +8 */
+ M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8);
break;
case ICMD_INVOKEVIRTUAL:
- gen_nullptr_check(REG_A0);
+ emit_nullpointer_check(cd, iptr, REG_OUT0);
if (lm == NULL) {
- codegen_addpatchref(cd, PATCHER_invokevirtual, um, 0);
-
- if (opt_showdisassemble) {
- M_NOP; M_NOP;
- }
+ codegen_add_patch_ref(cd, PATCHER_invokevirtual, um, 0);
s1 = 0;
}
s1 = OFFSET(vftbl_t, table[0]) +
sizeof(methodptr) * lm->vftblindex;
- M_ALD(REG_METHODPTR, REG_A0,
- OFFSET(java_objectheader, vftbl));
+ /* implicit null-pointer check */
+ M_ALD(REG_METHODPTR, REG_OUT0,OFFSET(java_objectheader, vftbl));
M_ALD(REG_PV_CALLER, REG_METHODPTR, s1);
- M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
- M_NOP;
-/* XXX no need to restore PV, when its in the regs */
+
+ /* generate the actual call */
+
+ M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
+ M_NOP;
+ disp = (s4) (cd->mcodeptr - cd->mcodebase);
+ /* REG_RA holds the value of the jmp instruction, therefore +8 */
+ M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8);
break;
case ICMD_INVOKEINTERFACE:
- /* XXX needs manual attention! */
- gen_nullptr_check(rd->argintregs[0]);
+ emit_nullpointer_check(cd, iptr, REG_OUT0);
if (lm == NULL) {
- codegen_addpatchref(cd, PATCHER_invokeinterface, um, 0);
-
- if (opt_showdisassemble) {
- M_NOP; M_NOP;
- }
+ codegen_add_patch_ref(cd, PATCHER_invokeinterface, um, 0);
s1 = 0;
s2 = 0;
s2 = sizeof(methodptr) * (lm - lm->class->methods);
}
- M_ALD(REG_METHODPTR, REG_A0,
- OFFSET(java_objectheader, vftbl));
+ /* implicit null-pointer check */
+ M_ALD(REG_METHODPTR, REG_OUT0, OFFSET(java_objectheader, vftbl));
M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
M_ALD(REG_PV_CALLER, REG_METHODPTR, s2);
- M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
- M_NOP;
-/* XXX no need to restore PV, when its in the regs */
+
+ /* generate the actual call */
+
+ M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
+ M_NOP;
+ disp = (s4) (cd->mcodeptr - cd->mcodebase);
+ /* REG_RA holds the value of the jmp instruction, therefore +8 */
+ M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8);
break;
}
- /* d contains return type */
+ /* store return value */
+
+ d = md->returntype.type;
if (d != TYPE_VOID) {
if (IS_INT_LNG_TYPE(d)) {
case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
- /* XXX needs manual attention! */
/* val.a: (classinfo*) superclass */
/* superclass is an interface:
if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
classinfo *super;
- vftbl_t *supervftbl;
s4 superindex;
- super = iptr->sx.s23.s3.c.cls;
-
- if (super == NULL) {
+ if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+ super = NULL;
superindex = 0;
- supervftbl = NULL;
}
else {
+ super = iptr->sx.s23.s3.c.cls;
superindex = super->index;
- supervftbl = super->vftbl;
}
#if defined(ENABLE_THREADS)
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- /* calculate interface checkcast code size */
-
- s2 = 8;
- if (super == NULL)
- s2 += (opt_showdisassemble ? 2 : 0);
-
- /* calculate class checkcast code size */
-
- s3 = 10 /* 10 + (s1 == REG_ITMP1) */;
- if (super == NULL)
- s3 += (opt_showdisassemble ? 2 : 0);
-
/* if class is not resolved, check which code to call */
if (super == NULL) {
- M_BEQZ(s1, 5 + (opt_showdisassemble ? 2 : 0) + s2 + 2 + s3);
- M_NOP;
+ emit_label_beqz(cd, BRANCH_LABEL_1, s1);
+ cr = iptr->sx.s23.s3.c.ref;
disp = dseg_add_unique_s4(cd, 0); /* super->flags */
- codegen_addpatchref(cd, PATCHER_checkcast_instanceof_flags,
- iptr->sx.s23.s3.c.ref,
- disp);
-
- if (opt_showdisassemble) {
- M_NOP; M_NOP;
- }
+ codegen_add_patch_ref(cd, PATCHER_checkcast_instanceof_flags,
+ cr, disp);
M_ILD(REG_ITMP2, REG_PV, disp);
M_AND_IMM(REG_ITMP2, ACC_INTERFACE, REG_ITMP2);
- M_BEQZ(REG_ITMP2, 1 + s2 + 2);
- M_NOP;
+ emit_label_beqz(cd, BRANCH_LABEL_2, REG_ITMP2);
}
/* interface checkcast code */
if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
if (super == NULL) {
- codegen_addpatchref(cd,
- PATCHER_checkcast_instanceof_interface,
- iptr->sx.s23.s3.c.ref,
- 0);
-
- if (opt_showdisassemble) {
- M_NOP; M_NOP;
- }
+ cr = iptr->sx.s23.s3.c.ref;
+
+ codegen_add_patch_ref(cd, PATCHER_checkcast_interface,
+ cr, 0);
}
else {
- M_BEQZ(s1, 1 + s2);
- M_NOP;
+ emit_label_beqz(cd, BRANCH_LABEL_3, s1);
}
M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
- M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
- M_LDA(REG_ITMP3, REG_ITMP3, -superindex);
- M_BLEZ(REG_ITMP3, 0);
- codegen_add_classcastexception_ref(cd, s1);
- M_NOP;
+ M_ILD(REG_ITMP3, REG_ITMP2,
+ OFFSET(vftbl_t, interfacetablelength));
+ M_ADD_IMM(REG_ITMP3, -superindex, REG_ITMP3);
+ emit_classcast_check(cd, iptr, ICMD_IFLE, REG_ITMP3, s1);
+
M_ALD(REG_ITMP3, REG_ITMP2,
- (s4) (OFFSET(vftbl_t, interfacetable[0]) -
- superindex * sizeof(methodptr*)));
- M_BEQZ(REG_ITMP3, 0);
- codegen_add_classcastexception_ref(cd, s1);
- M_NOP;
+ OFFSET(vftbl_t, interfacetable[0]) -
+ superindex * sizeof(methodptr*));
+ emit_classcast_check(cd, iptr, ICMD_IFEQ, REG_ITMP3, s1);
- if (super == NULL) {
- M_BR(1 + s3);
- M_NOP;
- }
+ if (super == NULL)
+ emit_label_br(cd, BRANCH_LABEL_4);
+ else
+ emit_label(cd, BRANCH_LABEL_3);
}
/* class checkcast code */
if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
if (super == NULL) {
+ emit_label(cd, BRANCH_LABEL_2);
+
+ cr = iptr->sx.s23.s3.c.ref;
disp = dseg_add_unique_address(cd, NULL);
- codegen_addpatchref(cd,
+ codegen_add_patch_ref(cd,
PATCHER_checkcast_instanceof_class,
- iptr->sx.s23.s3.c.ref,
- disp);
-
- if (opt_showdisassemble) {
- M_NOP; M_NOP;
- }
+ cr, disp);
}
else {
- disp = dseg_add_address(cd, supervftbl);
+ disp = dseg_add_address(cd, super->vftbl);
- M_BEQZ(s1, 1 + s3);
- M_NOP;
+ emit_label_beqz(cd, BRANCH_LABEL_5, s1);
}
M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
#endif
M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
- /* if (s1 != REG_ITMP1) { */
- /* M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, baseval)); */
- /* M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval)); */
- /* #if defined(ENABLE_THREADS) */
- /* codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase); */
- /* #endif */
- /* M_ISUB(REG_ITMP2, REG_ITMP1, REG_ITMP2); */
-
- /* } else { */
M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
M_SUB(REG_ITMP2, REG_ITMP3, REG_ITMP2);
M_ALD(REG_ITMP3, REG_PV, disp);
#endif
/* } */
M_CMP(REG_ITMP3, REG_ITMP2);
- M_BULT(0); /* branch if ITMP3 < ITMP2 */
- codegen_add_classcastexception_ref(cd, s1);
- M_NOP;
+ emit_classcast_check(cd, iptr, BRANCH_ULT, REG_ITMP3, s1);
+
+ if (super != NULL)
+ emit_label(cd, BRANCH_LABEL_5);
+ }
+
+ if (super == NULL) {
+ emit_label(cd, BRANCH_LABEL_1);
+ emit_label(cd, BRANCH_LABEL_4);
}
d = codegen_reg_of_dst(jd, iptr, s1);
s1 = emit_load_s1(jd, iptr, rd->argintregs[0]);
M_INTMOVE(s1, rd->argintregs[0]);
- disp = dseg_addaddress(cd, iptr->sx.s23.s3.c.cls);
+ disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
- codegen_addpatchref(cd, PATCHER_builtin_arraycheckcast,
- iptr->sx.s23.s3.c.ref,
- disp);
+ cr = iptr->sx.s23.s3.c.ref;
+ disp = dseg_add_unique_address(cd, NULL);
- if (opt_showdisassemble) {
- M_NOP; M_NOP;
- }
+ codegen_add_patch_ref(cd, PATCHER_builtin_arraycheckcast,
+ cr, disp);
}
+ else
+ disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
M_ALD(rd->argintregs[1], REG_PV, disp);
- disp = dseg_addaddress(cd, BUILTIN_arraycheckcast);
+ disp = dseg_add_functionptr(cd, BUILTIN_arraycheckcast);
M_ALD(REG_ITMP3, REG_PV, disp);
+ /* XXX jit-c-call */
M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
M_NOP;
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- M_BEQZ(REG_RESULT_CALLER, 0);
- codegen_add_classcastexception_ref(cd, s1);
- M_NOP;
+ emit_classcast_check(cd, iptr, ICMD_IFEQ, REG_RESULT_CALLER, s1);
d = codegen_reg_of_dst(jd, iptr, s1);
}
emit_store_dst(jd, iptr, d);
break;
+ case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
+ /* val.a: (classinfo*) superclass */
+
+ /* superclass is an interface:
+ *
+ * return (sub != NULL) &&
+ * (sub->vftbl->interfacetablelength > super->index) &&
+ * (sub->vftbl->interfacetable[-super->index] != NULL);
+ *
+ * superclass is a class:
+ *
+ * return ((sub != NULL) && (0
+ * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
+ * super->vftbl->diffvall));
+ */
+
+ {
+ classinfo *super;
+ vftbl_t *supervftbl;
+ s4 superindex;
+
+ if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+ super = NULL;
+ superindex = 0;
+ supervftbl = NULL;
+
+ } else {
+ super = iptr->sx.s23.s3.c.cls;
+ superindex = super->index;
+ supervftbl = super->vftbl;
+ }
+
+#if defined(ENABLE_THREADS)
+ codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
+#endif
+ s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+ d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+ if (s1 == d) {
+ M_MOV(s1, REG_ITMP1);
+ s1 = REG_ITMP1;
+ }
+
+ M_CLR(d);
+
+ /* if class is not resolved, check which code to call */
+
+ if (super == NULL) {
+ emit_label_beqz(cd, BRANCH_LABEL_1, s1);
+
+ cr = iptr->sx.s23.s3.c.ref;
+ disp = dseg_add_unique_s4(cd, 0); /* super->flags */
+
+ codegen_add_patch_ref(cd, PATCHER_checkcast_instanceof_flags,
+ cr, disp);
+
+ M_ILD(REG_ITMP3, REG_PV, disp);
+ M_AND_IMM(REG_ITMP3, ACC_INTERFACE, REG_ITMP3);
+ emit_label_beqz(cd, BRANCH_LABEL_2, REG_ITMP3);
+ }
+
+ /* interface instanceof code */
+
+ if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
+ if (super == NULL) {
+ cr = iptr->sx.s23.s3.c.ref;
+
+ codegen_add_patch_ref(cd, PATCHER_instanceof_interface,
+ cr, 0);
+ }
+ else {
+ emit_label_beqz(cd, BRANCH_LABEL_3, s1);
+ }
+
+ M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
+ M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
+ M_CMP_IMM(REG_ITMP3, superindex);
+ M_BLE(4);
+ M_NOP;
+ M_ALD(REG_ITMP1, REG_ITMP1,
+ (s4) (OFFSET(vftbl_t, interfacetable[0]) -
+ superindex * sizeof(methodptr*)));
+ M_CMOVRNE_IMM(REG_ITMP1, 1, d); /* REG_ITMP1 != 0 */
+
+ if (super == NULL)
+ emit_label_br(cd, BRANCH_LABEL_4);
+ else
+ emit_label(cd, BRANCH_LABEL_3);
+ }
+
+ /* class instanceof code */
+
+ if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
+ if (super == NULL) {
+ emit_label(cd, BRANCH_LABEL_2);
+
+ cr = iptr->sx.s23.s3.c.ref;
+ disp = dseg_add_unique_address(cd, NULL);
+
+ codegen_add_patch_ref(cd, PATCHER_checkcast_instanceof_class,
+ cr, disp);
+ }
+ else {
+ disp = dseg_add_address(cd, supervftbl);
+
+ emit_label_beqz(cd, BRANCH_LABEL_5, s1);
+ }
+
+ M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
+ M_ALD(REG_ITMP2, REG_PV, disp);
+#if defined(ENABLE_THREADS)
+ codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
+#endif
+ M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
+ M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
+ M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
+#if defined(ENABLE_THREADS)
+ codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
+#endif
+ M_SUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
+ M_CMP(REG_ITMP1, REG_ITMP2);
+ M_XCMOVULE_IMM(1, d);
+
+ if (super != NULL)
+ emit_label(cd, BRANCH_LABEL_5);
+ }
+
+ if (super == NULL) {
+ emit_label(cd, BRANCH_LABEL_1);
+ emit_label(cd, BRANCH_LABEL_4);
+ }
+
+ emit_store_dst(jd, iptr, d);
+ }
+ break;
+
+ case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
+
+ /* check for negative sizes and copy sizes to stack if necessary */
+
+ MCODECHECK((iptr->s1.argcount << 1) + 64);
+
+ for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
+
+ var = VAR(iptr->sx.s23.s2.args[s1]);
+
+ /* copy SAVEDVAR sizes to stack */
+
+ /* Already Preallocated? */
+
+ if (!(var->flags & PREALLOC)) {
+ s2 = emit_load(jd, iptr, var, REG_ITMP1);
+ M_STX(s2, REG_SP, CSTACK + (s1 * 8));
+ }
+ }
+
+ /* arg 0 = dimension count */
+
+ ICONST(REG_OUT0, iptr->s1.argcount);
+
+ /* is patcher function set? */
+
+ if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+ disp = dseg_add_unique_address(cd, 0);
+
+ codegen_add_patch_ref(cd, PATCHER_builtin_multianewarray,
+ iptr->sx.s23.s3.c.ref,
+ disp);
+ }
+ else
+ disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
+
+ /* arg 1 = arraydescriptor */
+
+ M_ALD(REG_OUT1, REG_PV, disp);
+ /* arg 2 = pointer to dimensions = stack pointer (absolute) */
+
+ M_ADD_IMM(REG_SP, CSTACK, REG_OUT2);
+
+ /* XXX c abi call */
+ disp = dseg_add_functionptr(cd, BUILTIN_multianewarray);
+ M_ALD(REG_ITMP3, REG_PV, disp);
+ M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
+ M_NOP;
+
+ /* check for exception before result assignment */
+
+ emit_exception_check(cd, iptr);
+
+ d = codegen_reg_of_dst(jd, iptr, REG_RESULT_CALLER);
+ M_INTMOVE(REG_RESULT_CALLER, d);
+ emit_store_dst(jd, iptr, d);
+ break;
default:
- *exceptionptr = new_internalerror("Unknown ICMD %d", iptr->opc);
+ exceptions_throw_internalerror("Unknown ICMD %d during code generation",
+ iptr->opc);
return false;
} /* switch */
} /* for instruction */
- /* copy values to interface registers */
- src = bptr->outstack;
- len = bptr->outdepth;
- MCODECHECK(64+len);
-#if defined(ENABLE_LSRA)
- if (!opt_lsra)
-#endif
- while (src) {
- len--;
- if ((src->varkind != STACKVAR)) {
- s2 = src->type;
- if (IS_FLT_DBL_TYPE(s2)) {
- s1 = emit_load(jd, NULL, src, REG_FTMP1);
- if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
- M_FLTMOVE(s1,rd->interfaces[len][s2].regoff);
- }
- else {
- M_DST(s1, REG_SP, 8 * rd->interfaces[len][s2].regoff);
- }
- }
- else {
- s1 = emit_load(jd, NULL, src, REG_ITMP1);
- if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
- M_INTMOVE(s1,rd->interfaces[len][s2].regoff);
- }
- else {
- M_STX(s1, REG_SP, 8 * rd->interfaces[len][s2].regoff);
- }
- }
- }
- src = src->prev;
- }
+
} /* if (bptr -> flags >= BBREACHED) */
} /* for basic block */
/* generate stubs */
- emit_exception_stubs(jd);
emit_patcher_stubs(jd);
- emit_replacement_stubs(jd);
-
- codegen_finish(jd);
+ REPLACEMENT_EMIT_STUBS(jd);
/* everything's ok */
}
-
-
-
/* createcompilerstub **********************************************************
Creates a stub routine which calls the compiler.
u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
{
- /* fabort("help me!"); */
- printf("createnativestub not implemented\n");
- return NULL;
+ methodinfo *m;
+ codeinfo *code;
+ codegendata *cd;
+ registerdata *rd;
+ methoddesc *md;
+ s4 nativeparams;
+ s4 i, j; /* count variables */
+ s4 t;
+ s4 s1, s2, disp;
+ s4 funcdisp; /* displacement of the function */
+
+ /* get required compiler data */
+
+ m = jd->m;
+ code = jd->code;
+ cd = jd->cd;
+ rd = jd->rd;
+
+ /* initialize variables */
+
+ md = m->parseddesc;
+ nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
+
+ /* calculate stack frame size */
+
+ cd->stackframesize =
+ sizeof(stackframeinfo) / SIZEOF_VOID_P +
+ sizeof(localref_table) / SIZEOF_VOID_P +
+ md->paramcount + /* for saving arguments over calls */
+ nmd->memuse + /* nmd knows about the native stackframe layout */
+ WINSAVE_CNT;
+
+ /* create method header */
+
+ (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
+ (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 */
+ (void) dseg_add_unique_s4(cd, 0); /* FltSave */
+ (void) dseg_addlinenumbertablesize(cd);
+ (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */
+
+ /* generate stub code */
+
+ M_SAVE(REG_SP, -cd->stackframesize * 8, REG_SP); /* build up stackframe */
+
+#if !defined(NDEBUG)
+ if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
+ emit_verbosecall_enter(jd);
+#endif
+
+ /* get function address (this must happen before the stackframeinfo) */
+
+ funcdisp = dseg_add_functionptr(cd, f);
+
+#if !defined(WITH_STATIC_CLASSPATH)
+ if (f == NULL) {
+ codegen_add_patch_ref(cd, PATCHER_resolve_native, m, funcdisp);
+ }
+#endif
+
+ /* save float argument registers */
+
+ for (i = 0, j = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
+ if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
+ M_DST(rd->argfltregs[i], REG_SP, CSTACK + (j * 8));
+ j++;
+ }
+ }
+
+ /* prepare data structures for native function call */
+
+ M_ADD_IMM(REG_FP, BIAS, REG_OUT0); /* datasp == top of the stack frame (absolute == +BIAS) */
+ M_MOV(REG_PV_CALLEE, REG_OUT1);
+ M_MOV(REG_FP, REG_OUT2); /* java sp */
+ M_MOV(REG_RA_CALLEE, REG_OUT3);
+ disp = dseg_add_functionptr(cd, codegen_start_native_call);
+ M_ALD(REG_ITMP3, REG_PV_CALLEE, disp);
+ M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
+ M_NOP; /* XXX fill me! */
+
+ /* restore float argument registers */
+
+ for (i = 0, j = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
+ if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
+ M_DLD(rd->argfltregs[i], REG_SP, CSTACK + (j * 8));
+ j++;
+ }
+ }
+
+ /* copy or spill arguments to new locations */
+ int num_fltregargs = 0;
+ int fltregarg_inswap[16];
+ for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
+ t = md->paramtypes[i].type;
+
+ if (IS_INT_LNG_TYPE(t)) {
+ if (!md->params[i].inmemory) {
+ s1 = rd->argintregs[md->params[i].regoff];
+ /* s1 refers to the old window, transpose */
+ s1 = REG_WINDOW_TRANSPOSE(s1);
+
+ if (!nmd->params[j].inmemory) {
+ s2 = nat_argintregs[nmd->params[j].regoff];
+ M_INTMOVE(s1, s2);
+ } else {
+ s2 = nmd->params[j].regoff - 6;
+ M_AST(s1, REG_SP, CSTACK + s2 * 8);
+ }
+
+ } else {
+ s1 = md->params[i].regoff + cd->stackframesize;
+ s2 = nmd->params[j].regoff - 6;
+ M_ALD(REG_ITMP1, REG_SP, CSTACK + s1 * 8);
+ M_AST(REG_ITMP1, REG_SP, CSTACK + s2 * 8);
+ }
+
+ } else {
+ if (!md->params[i].inmemory) {
+ s1 = rd->argfltregs[md->params[i].regoff];
+
+ if (!nmd->params[j].inmemory) {
+ /* no mapping to regs needed, native flt args use regoff */
+ s2 = nmd->params[j].regoff;
+
+ /* we cannot move flt regs to their native arg locations directly */
+ M_DMOV(s1, s2 + 16);
+ fltregarg_inswap[num_fltregargs] = s2;
+ num_fltregargs++;
+ printf("flt arg swap to %d\n", s2 + 16);
+
+ } else {
+ s2 = nmd->params[j].regoff;
+ if (IS_2_WORD_TYPE(t))
+ M_DST(s1, REG_SP, CSTACK + (s2 * 8));
+ else
+ M_FST(s1, REG_SP, CSTACK + (s2 * 8));
+ }
+
+ } else {
+ s1 = md->params[i].regoff + cd->stackframesize;
+ s2 = nmd->params[j].regoff - 6;
+ if (IS_2_WORD_TYPE(t)) {
+ M_DLD(REG_FTMP1, REG_SP, CSTACK + s1 * 8);
+ M_DST(REG_FTMP1, REG_SP, CSTACK + s2 * 8);
+ } else {
+ M_FLD(REG_FTMP1, REG_SP, CSTACK + s1 * 8);
+ M_FST(REG_FTMP1, REG_SP, CSTACK + s2 * 8);
+ }
+ }
+ }
+ }
+
+ /* move swapped float args to target regs */
+ for (i = 0; i < num_fltregargs; i++) {
+ s1 = fltregarg_inswap[i];
+ M_DMOV(s1 + 16, s1);
+ printf("float arg to target reg: %d ==> %d\n", s1+16, s1);
+ }
+
+
+ /* put class into second argument register */
+
+ if (m->flags & ACC_STATIC) {
+ disp = dseg_add_address(cd, m->class);
+ M_ALD(REG_OUT1, REG_PV_CALLEE, disp);
+ }
+
+ /* put env into first argument register */
+
+ disp = dseg_add_address(cd, _Jv_env);
+ M_ALD(REG_OUT0, REG_PV_CALLEE, disp);
+
+ /* do the native function call */
+
+ M_ALD(REG_ITMP3, REG_PV_CALLEE, funcdisp); /* load adress of native method */
+ M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO); /* call native method */
+ M_NOP; /* delay slot */
+
+ /* save return value */
+
+ if (md->returntype.type != TYPE_VOID) {
+ if (IS_INT_LNG_TYPE(md->returntype.type))
+ M_MOV(REG_RESULT_CALLER, REG_RESULT_CALLEE);
+ else
+ M_DST(REG_FRESULT, REG_SP, CSTACK);
+ }
+
+ /* Note: native functions return float values in %f0 (see ABI) */
+ /* we handle this by doing M_FLD below. (which will load the lower word into %f1) */
+
+#if !defined(NDEBUG)
+ /* But for the trace function we need to put a flt result into %f1 */
+ if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
+ if (!IS_2_WORD_TYPE(md->returntype.type))
+ M_FLD(REG_FRESULT, REG_SP, CSTACK);
+ emit_verbosecall_exit(jd);
+ }
+#endif
+
+ /* remove native stackframe info */
+
+ M_ADD_IMM(REG_FP, BIAS, REG_OUT0); /* datasp, like above */
+ disp = dseg_add_functionptr(cd, codegen_finish_native_call);
+ M_ALD(REG_ITMP3, REG_PV_CALLEE, disp);
+ M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
+ M_NOP; /* XXX fill me! */
+ M_MOV(REG_RESULT_CALLER, REG_ITMP2_XPTR);
+
+ /* restore float return value, int return value already in our return reg */
+
+ if (md->returntype.type != TYPE_VOID) {
+ if (IS_FLT_DBL_TYPE(md->returntype.type)) {
+ if (IS_2_WORD_TYPE(md->returntype.type))
+ M_DLD(REG_FRESULT, REG_SP, CSTACK);
+ else
+ M_FLD(REG_FRESULT, REG_SP, CSTACK);
+ }
+ }
+
+ /* check for exception */
+
+ M_BNEZ(REG_ITMP2_XPTR, 4); /* if no exception then return */
+ M_NOP;
+
+ M_RETURN(REG_RA_CALLEE, 8); /* implicit window restore */
+ M_NOP;
+#if 0
+ M_RESTORE(REG_ZERO, 0, REG_ZERO); /* restore callers window (DELAY) */
+
+ M_RET(REG_RA_CALLER, 8); /* return to caller */
+ M_NOP; /* DELAY SLOT */
+#endif
+
+ /* handle exception */
+
+ disp = dseg_add_functionptr(cd, asm_handle_nat_exception);
+ M_ALD(REG_ITMP3, REG_PV, disp); /* load asm exception handler address */
+ M_JMP(REG_ZERO, REG_ITMP3, REG_ZERO);/* jump to asm exception handler */
+ M_MOV(REG_RA_CALLEE, REG_ITMP3_XPC); /* get exception address (DELAY) */
+
+ /* generate patcher stubs */
+
+ emit_patcher_stubs(jd);
+
+ codegen_finish(jd);
+
+ return code->entrypoint;
}
/*