/* 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 <stdint.h>
+#include <stdio.h>
#include "vm/types.h"
#include "mm/memory.h"
#include "native/jni.h"
+#include "native/localref.h"
#include "native/native.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/abi.h"
#include "vm/jit/asmpart.h"
#include "vm/jit/codegen-common.h"
#include "vm/jit/dseg.h"
-#include "vm/jit/emit.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"
+
+#include "vm/jit/sparc64/solaris/macro_rename.h"
+
+#define BUILTIN_FLOAT_ARGS 1
/* 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)
+{
+ 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;
+}
+
+#ifndef NDEBUG
+bool check_13bit_imm(s8 imm)
{
- fprintf(stderr, "sparc64 abort because: %s\n", x);
- exit(1);
- abort();
- return 0;
-
+ s4 sign = (imm >> 12) & 0x1;
+
+ if (sign == 0) {
+ if ((imm & ~0xfff) == 0) return true; /* pos imm. */
+ }
+ else
+ if ((imm & ~0xfff) + 0xfff == -1) return true; /* neg imm. */
+
+ printf("immediate out-of-bounds: %ld\n", imm);
+ return false;
}
+#endif
+
-/* 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;
+ s4 len, s1, s2, s3, d, disp, slots;
varinfo *var;
basicblock *bptr;
instruction *iptr;
- exceptiontable *ex;
+ 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 framesize_disp;
#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 */
+ framesize_disp = 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, JITSTACK + (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, cd->exceptiontablelength); /* ExTableSize */
-
/* create exception table */
- for (ex = cd->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);
+ for (ex = jd->exceptiontable; ex != NULL; ex = ex->down) {
+ 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);
-
- /* save return address and used callee saved registers */
+ if (cd->stackframesize) {
+ if (cd->stackframesize <= 4095)
+ M_SAVE(REG_SP, -cd->stackframesize * 8, REG_SP);
+ else {
+ M_ILD_INTERN(REG_ITMP3, REG_PV_CALLER, framesize_disp);
+ M_SUB(REG_ZERO, REG_ITMP3, REG_ITMP3);
+ M_SAVE_REG(REG_SP, REG_ITMP3, REG_SP);
+ }
+ }
- 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 */
+
+ /* call monitorenter function */
+#if defined(ENABLE_THREADS)
+ if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
+ /* stack offset for monitor argument */
+
+ s1 = rd->memuse;
+
+ /* save float argument registers */
+
+ /* XXX jit-c-call */
+ slots = FLT_ARG_CNT;
+ ALIGN_STACK_SLOTS(slots);
+
+ M_LDA(REG_SP, REG_SP, -(slots * 8));
+ for (i = 0; i < FLT_ARG_CNT; i++)
+ M_DST(abi_registers_float_argument[i], REG_SP, CSTACK + i * 8);
+ s1 += slots;
+
+ /* get correct lock object */
+
+ if (m->flags & ACC_STATIC) {
+ disp = dseg_add_address(cd, &m->class->object.header);
+ M_ALD(REG_OUT0, REG_PV, disp);
+ disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
+ M_ALD(REG_ITMP3, REG_PV, disp);
+ }
+ else {
+ /* copy class pointer: $i0 -> $o0 */
+ M_MOV(REG_RESULT_CALLEE, REG_OUT0);
+ M_BNEZ(REG_OUT0, 3);
+ disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
+ M_ALD(REG_ITMP3, REG_PV, disp); /* branch delay */
+ M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_NULLPOINTER);
+ }
+
+ M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
+ M_AST(REG_OUT0, REG_SP, CSTACK + s1 * 8); /* branch delay */
+
+ /* restore float argument registers */
+
+ for (i = 0; i < FLT_ARG_CNT; i++)
+ M_DLD(abi_registers_float_argument[i], REG_SP, CSTACK + i * 8);
+
+ M_LDA(REG_SP, REG_SP, slots * 8);
+ }
+#endif
+
+
+ /* take arguments out of register or stack frame */
+
md = m->parseddesc;
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;
- s1 = md->params[p].regoff;
- if (IS_INT_LNG_TYPE(t)) { /* integer args */
+
+ var = VAR(varindex);
+ s1 = md->params[p].regoff;
+
+ if (IS_INT_LNG_TYPE(t)) { /* integer args */
+
+ s2 = var->vv.regoff;
+
if (!md->params[p].inmemory) { /* register arguments */
- s2 = rd->argintregs[s1];
+ s1 = REG_WINDOW_TRANSPOSE(s1);
+
if (!(var->flags & INMEMORY)) { /* reg arg -> register */
- M_INTMOVE(s2, var->regoff);
- } else { /* reg arg -> spilled */
- M_STX(s2, REG_SP, (WINSAVE_REGS + var->regoff) * 8);
+ /* the register allocator does not know about the window. */
+ /* avoid copying the locals from save to save regs by */
+ /* swapping variables. */
+
+ {
+ int old_dest = var->vv.regoff;
+ int new_dest = p + 24;
+
+ /* run through all variables */
+
+ for (i = 0; i < jd->varcount; i++) {
+ varinfo* uvar = VAR(i);
+
+ if (IS_FLT_DBL_TYPE(uvar->type) || IS_INMEMORY(uvar->flags))
+ continue;
+
+ s2 = uvar->vv.regoff;
+
+ /* free the in reg by moving all other references */
+
+ if (s2 == new_dest) {
+ uvar->vv.regoff = old_dest;
+ /*printf("p%d-var[%d]: moved %d -> %d (to free save reg)\n", p, i, s2, old_dest);*/
+ }
+
+ /* move all variables to the in reg */
+
+ if (s2 == old_dest) {
+ uvar->vv.regoff = new_dest;
+ /*printf("p%d-var[%d]: moved %d -> %d (to avoid copy)\n", p, i, s2, new_dest);*/
+ }
+ }
+ }
+
+
+
+ }
+ else { /* reg arg -> spilled */
+ M_STX(s1, REG_SP, JITSTACK + var->vv.regoff);
}
} 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);
} else { /* stack arg -> spilled */
- var->regoff = stackframesize + s1;
+ /* add the callers window save registers */
+ var->vv.regoff = cd->stackframesize * 8 + s1;
}
}
} else { /* floating args */
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(s1, var->vv.regoff);
} else { /* reg arg -> spilled */
- M_DST(s2, REG_SP, (WINSAVE_REGS + var->regoff) * 8);
+ M_DST(s1, REG_SP, JITSTACK + var->vv.regoff);
}
} 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);
} else { /* stack-arg -> spilled */
- var->regoff = stackframesize + s1;
+ var->vv.regoff = cd->stackframesize * 8 + s1;
}
}
}
} /* end for */
- /* XXX monitor enter and tracing */
-
}
/* end of header generation */
- replacementpoint = jd->code->rplpoints;
+ /* create replacement points */
+
+ REPLACEMENT_POINTS_INIT(cd, jd);
/* walk through all basic blocks */
- for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
+ for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
bptr->mpc = (s4) (cd->mcodeptr - cd->mcodebase);
/* 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 */
- src = bptr->instack;
len = bptr->icount;
- for (iptr = bptr->iinstr; len > 0; src = iptr->dst, len--, iptr++) {
+ for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
if (iptr->line != currentline) {
dseg_addlinenumber(cd, iptr->line);
currentline = iptr->line;
}
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 ((iptr->target != NULL) && (iptr->sx.val.anyptr == NULL)) {
- disp = dseg_addaddress(cd, iptr->sx.val.anyptr);
-
- codegen_addpatchref(cd, PATCHER_aconst,
- (unresolved_class *) iptr->target, disp);
+ if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+ cr = iptr->sx.val.c.ref;
+ disp = dseg_add_unique_address(cd, cr);
- if (opt_showdisassemble) {
- M_NOP;
- }
+ codegen_add_patch_ref(cd, PATCHER_aconst, cr, disp);
- M_ALD(REG_PV, disp, d);
+ 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_LLOAD:
case ICMD_ALOAD:
+ case ICMD_FLOAD:
+ case ICMD_DLOAD:
+ case ICMD_ISTORE: /* ..., value ==> ... */
+ case ICMD_LSTORE:
+ case ICMD_FSTORE:
+ case ICMD_DSTORE:
+ case ICMD_COPY:
+ case ICMD_MOVE:
- 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);
+ emit_copy(jd, iptr);
break;
- 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_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);
- }
+ if (!(iptr->flags.bits & INS_FLAG_RETADDR))
+ emit_copy(jd, iptr);
break;
- case ICMD_FSTORE: /* ..., value ==> ... */
- case ICMD_DSTORE: /* op1 = local variable */
-
- 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);
- }
- break;
-
/* pop/dup/swap operations ********************************************/
case ICMD_POP2: /* ..., value, value ==> ... */
break;
- case ICMD_DUP: /* ..., a ==> ..., a, a */
- M_COPY(src, iptr->dst);
- break;
-
- case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
-
- M_COPY(src, iptr->dst);
- M_COPY(src->prev, iptr->dst->prev);
- M_COPY(iptr->dst, iptr->dst->prev->prev);
- break;
-
- case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
-
- M_COPY(src, iptr->dst);
- M_COPY(src->prev, iptr->dst->prev);
- M_COPY(src->prev->prev, iptr->dst->prev->prev);
- M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
- break;
-
- case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
-
- M_COPY(src, iptr->dst);
- M_COPY(src->prev, iptr->dst->prev);
- break;
-
- case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
-
- M_COPY(src, iptr->dst);
- M_COPY(src->prev, iptr->dst->prev);
- M_COPY(src->prev->prev, iptr->dst->prev->prev);
- M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
- M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev);
- break;
-
- case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
-
- M_COPY(src, iptr->dst);
- M_COPY(src->prev, iptr->dst->prev);
- M_COPY(src->prev->prev, iptr->dst->prev->prev);
- M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
- M_COPY(iptr->dst, iptr->dst->prev->prev->prev->prev);
- M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev->prev);
- break;
-
- case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
-
- M_COPY(src, iptr->dst->prev);
- M_COPY(src->prev, iptr->dst);
- 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);
emit_store_dst(jd, iptr, d);
break;
- case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
+ case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
/* sx.val.i = constant */
+ /* constant is actually constant - 1 */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
- M_ISEXT(s1, s1); /* trim for 32-bit compare (BGEZ) */
if (s1 == d) {
M_MOV(s1, REG_ITMP1);
s1 = REG_ITMP1;
}
- if ((iptr->sx.val.i >= 0) && (iptr->sx.val.i <= 0xffff)) {
+ M_ISEXT(s1, s1); /* trim for 32-bit compare (BGEZ) */
+ if ((iptr->sx.val.i >= 0) && (iptr->sx.val.i <= 4095)) {
M_AND_IMM(s1, iptr->sx.val.i, d);
- M_BGEZ(s1, 4);
+ M_BGEZ(s1, 5);
M_NOP;
M_SUB(REG_ZERO, s1, d);
M_AND_IMM(d, iptr->sx.val.i, d);
} else {
ICONST(REG_ITMP2, iptr->sx.val.i);
M_AND(s1, REG_ITMP2, d);
- M_BGEZ(s1, 4);
+ M_BGEZ(s1, 5);
M_NOP;
M_SUB(REG_ZERO, s1, d);
M_AND(d, REG_ITMP2, d);
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_unique_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_unique_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_L2F:
+ s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+ d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
+ disp = dseg_add_unique_double(cd, 0.0);
+ M_STX(s1, REG_PV_CALLEE, disp);
+ M_DLD(REG_FTMP3, REG_PV_CALLEE, disp);
+ M_CVTLF(REG_FTMP3, d);
+ emit_store_dst(jd, iptr, d);
+ break;
+
+ case ICMD_L2D:
+ s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+ d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
+ disp = dseg_add_unique_double(cd, 0.0);
+ M_STX(s1, REG_PV_CALLEE, disp);
+ M_DLD(d, REG_PV_CALLEE, disp);
+ M_CVTLD(d, d);
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_unique_float(cd, 0.0);
+
+ /* check for NaN, SPARC overflow is noncompliant (see V9 spec B.5) */
+ M_FCMP(s1, s1);
+ M_FBU(5);
+ M_MOV(REG_ZERO, d); /* delay slot */
+
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_unique_float(cd, 0.0);
+
+ /* check for NaN, SPARC overflow is noncompliant (see V9 spec B.5) */
+ M_DCMP(s1, s1);
+ M_FBU(5);
+ M_MOV(REG_ZERO, d); /* delay slot */
+
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_unique_double(cd, 0.0);
+
+ /* check for NaN, SPARC overflow is noncompliant (see V9 spec B.5) */
+ M_FCMP(s1, s1);
+ M_FBU(5);
+ M_MOV(REG_ZERO, d); /* delay slot */
+
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_unique_double(cd, 0.0);
+
+ /* check for NaN, SPARC overflow is noncompliant (see V9 spec B.5) */
+ M_DCMP(s1, s1);
+ M_FBU(5);
+ M_MOV(REG_ZERO, d); /* delay slot */
+
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);
- M_ILD(d, s1, OFFSET(java_arrayheader, size));
+ emit_nullpointer_check(cd, iptr, s1);
+ M_ILD(d, s1, OFFSET(java_array_t, 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_t, 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]));
+ M_SLDU(d, REG_ITMP3, OFFSET(java_chararray_t, 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_SLDS(d, REG_ITMP3, OFFSET(java_chararray, data[0]));
+ M_SLDS(d, REG_ITMP3, OFFSET(java_shortarray_t, 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]));
+ M_ILD(d, REG_ITMP3, OFFSET(java_intarray_t, 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, 3, REG_ITMP3);
M_AADD(REG_ITMP3, s1, REG_ITMP3);
- M_LDX(d, REG_ITMP3, OFFSET(java_longarray, data[0]));
+ M_LDX(d, REG_ITMP3, OFFSET(java_longarray_t, 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_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]));
+ M_FLD(d, REG_ITMP3, OFFSET(java_floatarray_t, 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_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]));
+ M_DLD(d, REG_ITMP3, OFFSET(java_doublearray_t, 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, POINTERSHIFT, REG_ITMP3);
M_AADD(REG_ITMP3, s1, REG_ITMP3);
- M_ALD(d, REG_ITMP3, OFFSET(java_objectarray, data[0]));
+ M_ALD(d, REG_ITMP3, OFFSET(java_objectarray_t, 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);
- 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]));
+ M_BST(s3, REG_ITMP1, OFFSET(java_bytearray_t, data[0]));
break;
case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
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);
- M_SST(s3, REG_ITMP1, OFFSET(java_chararray, data[0]));
+ M_SST(s3, REG_ITMP1, OFFSET(java_chararray_t, data[0]));
break;
case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
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);
- M_IST_INTERN(s3, REG_ITMP1, OFFSET(java_intarray, data[0]));
+ M_IST_INTERN(s3, REG_ITMP1, OFFSET(java_intarray_t, data[0]));
break;
case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
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);
- M_STX_INTERN(s3, REG_ITMP1, OFFSET(java_longarray, data[0]));
+ M_STX_INTERN(s3, REG_ITMP1, OFFSET(java_longarray_t, data[0]));
break;
case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
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);
- M_FST_INTERN(s3, REG_ITMP1, OFFSET(java_floatarray, data[0]));
+ M_FST_INTERN(s3, REG_ITMP1, OFFSET(java_floatarray_t, data[0]));
break;
case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
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);
- M_DST_INTERN(s3, REG_ITMP1, OFFSET(java_doublearray, data[0]));
+ M_DST_INTERN(s3, REG_ITMP1, OFFSET(java_doublearray_t, 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);
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);
+ M_MOV(s1, REG_OUT0);
+ M_MOV(s3, REG_OUT1);
+ 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);
- M_AST_INTERN(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
+ /* implicit null-pointer check */
+ M_AST_INTERN(s3, REG_ITMP1, OFFSET(java_objectarray_t, 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]));
+ M_BST(REG_ZERO, REG_ITMP1, OFFSET(java_bytearray_t, data[0]));
break;
case ICMD_CASTORECONST: /* ..., arrayref, index ==> ... */
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]));
+ M_SST(REG_ZERO, REG_ITMP1, OFFSET(java_chararray_t, data[0]));
break;
case ICMD_IASTORECONST: /* ..., arrayref, index ==> ... */
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]));
+ M_IST_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_intarray_t, data[0]));
break;
case ICMD_LASTORECONST: /* ..., arrayref, index ==> ... */
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]));
+ M_STX_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_longarray_t, data[0]));
break;
case ICMD_AASTORECONST: /* ..., arrayref, index ==> ... */
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]));
+ M_AST_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_objectarray_t, data[0]));
break;
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,
- 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:
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 ==> ... */
- /* op1 = target JavaVM pc, val.i = constant */
- s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
- if (iptr->val.i == 0) {
- M_BLTZ(s1, 0);
- } else {
- if ((iptr->val.i >= -4096) && (iptr->val.i <= 4095)) {
- M_CMP_IMM(s1, iptr->val.i);
- } else {
- ICONST(REG_ITMP2, iptr->val.i);
- M_CMP(s1, REG_ITMP2);
- }
- M_BGT(0);
+ s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+
+ 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, (basicblock *) iptr->target);
- M_NOP;
+ emit_bgt(cd, iptr->dst.block);
break;
case ICMD_IFGE: /* ..., value ==> ... */
- /* op1 = target JavaVM pc, val.i = constant */
- s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
- if (iptr->val.i == 0) {
- M_BLEZ(s1, 0);
- }
+ s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+
+ if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
+ M_CMP_IMM(s1, iptr->sx.val.i);
+ }
else {
- if ((iptr->val.i >= -4096) && (iptr->val.i <= 4095)) {
- M_CMP_IMM(s1, iptr->val.i);
- }
- else {
- ICONST(REG_ITMP2, iptr->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, (basicblock *) iptr->target);
- M_NOP;
+ emit_bge(cd, iptr->dst.block);
break;
case ICMD_IF_LEQ: /* ..., value ==> ... */
- /* op1 = target JavaVM pc, val.l = constant */
- s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
- if (iptr->val.l == 0) {
- M_BEQZ(s1, 0);
- }
+ s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+ if (iptr->sx.val.l == 0)
+ emit_beqz(cd, iptr->dst.block, s1);
else {
- if ((iptr->val.l >= -4096) && (iptr->val.l <= 4095)) {
- M_CMP_IMM(s1, iptr->val.l);
+ if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
+ M_CMP_IMM(s1, iptr->sx.val.l);
}
else {
- LCONST(REG_ITMP2, iptr->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, (basicblock *) iptr->target);
- M_NOP;
break;
case ICMD_IF_LLT: /* ..., value ==> ... */
- /* op1 = target JavaVM pc, val.l = constant */
- s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
- if (iptr->val.l == 0) {
- M_BLTZ(s1, 0);
- } else {
- if ((iptr->val.l >= -4096) && (iptr->val.l <= 4095)) {
- M_CMP_IMM(s1, iptr->val.l);
- } else {
- ICONST(REG_ITMP2, iptr->val.l);
+ s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+ 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 {
+ LCONST(REG_ITMP2, iptr->sx.val.l);
M_CMP(s1, REG_ITMP2);
}
- M_XBLT(0);
+ emit_blt_xcc(cd, iptr->dst.block);
}
- codegen_addreference(cd, (basicblock *) iptr->target);
- M_NOP;
break;
case ICMD_IF_LLE: /* ..., value ==> ... */
- /* op1 = target JavaVM pc, val.l = constant */
- s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
- if (iptr->val.l == 0) {
- M_BLEZ(s1, 0);
- }
+ s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+ if (iptr->sx.val.l == 0)
+ emit_blez(cd, iptr->dst.block, s1);
else {
- if ((iptr->val.l >= -4096) && (iptr->val.l <= 4095)) {
- M_CMP_IMM(s1, iptr->val.l);
- }
+ if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
+ M_CMP_IMM(s1, iptr->sx.val.l);
+ }
else {
- ICONST(REG_ITMP2, iptr->val.l);
+ LCONST(REG_ITMP2, iptr->sx.val.l);
M_CMP(s1, REG_ITMP2);
}
- M_XBLE(0);
+ emit_ble_xcc(cd, iptr->dst.block);
}
- codegen_addreference(cd, (basicblock *) iptr->target);
- M_NOP;
break;
case ICMD_IF_LNE: /* ..., value ==> ... */
- /* op1 = target JavaVM pc, val.l = constant */
- s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
- if (iptr->val.l == 0) {
- M_BNEZ(s1, 0);
- }
+ s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+ if (iptr->sx.val.l == 0)
+ emit_bnez(cd, iptr->dst.block, s1);
else {
- if ((iptr->val.l >= -4096) && (iptr->val.l <= 4095)) {
- M_CMP_IMM(s1, iptr->val.i);
+ if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
+ M_CMP_IMM(s1, iptr->sx.val.l);
}
else {
- ICONST(REG_ITMP2, iptr->val.l);
+ LCONST(REG_ITMP2, iptr->sx.val.l);
M_CMP(s1, REG_ITMP2);
}
- M_XBNE(0);
+ emit_bne_xcc(cd, iptr->dst.block);
}
- codegen_addreference(cd, (basicblock *) iptr->target);
- M_NOP;
break;
case ICMD_IF_LGT: /* ..., value ==> ... */
- /* op1 = target JavaVM pc, val.l = constant */
- s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
- if (iptr->val.l == 0) {
- M_BLTZ(s1, 0);
- } else {
- if ((iptr->val.l >= -4096) && (iptr->val.l <= 4095)) {
- M_CMP_IMM(s1, iptr->val.l);
- } else {
- ICONST(REG_ITMP2, iptr->val.l);
+ s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+ 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 {
+ LCONST(REG_ITMP2, iptr->sx.val.l);
M_CMP(s1, REG_ITMP2);
}
- M_XBGT(0);
+ emit_bgt_xcc(cd, iptr->dst.block);
}
- codegen_addreference(cd, (basicblock *) iptr->target);
- M_NOP;
break;
case ICMD_IF_LGE: /* ..., value ==> ... */
- /* op1 = target JavaVM pc, val.l = constant */
- s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
- if (iptr->val.l == 0) {
- M_BLEZ(s1, 0);
- }
+ s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+ if (iptr->sx.val.l == 0)
+ emit_bgez(cd, iptr->dst.block, s1);
else {
- if ((iptr->val.l >= -4096) && (iptr->val.l <= 4095)) {
- M_CMP_IMM(s1, iptr->val.l);
- }
+ if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
+ M_CMP_IMM(s1, iptr->sx.val.l);
+ }
else {
- ICONST(REG_ITMP2, iptr->val.l);
+ LCONST(REG_ITMP2, iptr->sx.val.l);
M_CMP(s1, REG_ITMP2);
}
- M_XBGE(0);
+ emit_bge_xcc(cd, iptr->dst.block);
}
- codegen_addreference(cd, (basicblock *) iptr->target);
- 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)
if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
-/* XXX: REG_RESULT is save, but what about FRESULT? */
- M_ALD(rd->argintregs[0], REG_SP, rd->memuse * 8); /* XXX: what for ? */
+ /* XXX jit-c-call */
+ disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
+ M_ALD(REG_ITMP3, REG_PV, disp);
+
+ /* we need to save fp return value (int saved by window) */
switch (iptr->opc) {
case ICMD_FRETURN:
case ICMD_DRETURN:
- M_DST(REG_FRESULT, REG_SP, rd->memuse * 8);
- break;
- }
+ M_ALD(REG_OUT0, REG_SP, CSTACK + rd->memuse * 8);
+ M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
+ M_DST(REG_FRESULT, REG_SP, CSTACK + rd->memuse * 8); /* delay */
- disp = dseg_addaddress(cd, BUILTIN_monitorexit);
- M_ALD(REG_ITMP3, REG_PV, disp);
- M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO); /*REG_RA_CALLER */
+ /* restore the fp return value */
- switch (iptr->opc) {
- case ICMD_FRETURN:
- case ICMD_DRETURN:
- M_DLD(REG_FRESULT, REG_SP, rd->memuse * 8);
+ M_DLD(REG_FRESULT, REG_SP, CSTACK + rd->memuse * 8);
+ break;
+ case ICMD_IRETURN:
+ case ICMD_LRETURN:
+ case ICMD_ARETURN:
+ case ICMD_RETURN:
+ M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
+ M_ALD(REG_OUT0, REG_SP, CSTACK + rd->memuse * 8); /* delay */
+ break;
+ default:
+ assert(false);
break;
}
}
- M_RETURN(REG_RA_CALLEE); /* implicit window restore */
+ M_RETURN(REG_RA_CALLEE, 8); /* implicit window restore */
M_NOP;
ALIGNCODENOP;
}
case ICMD_TABLESWITCH: /* ..., index ==> ... */
{
- s4 i, l, *s4ptr;
- void **tptr;
+ s4 i, l;
+ branch_target_t *table;
- tptr = (void **) iptr->target;
+ table = iptr->dst.table;
- s4ptr = iptr->val.a;
- l = s4ptr[1]; /* low */
- i = s4ptr[2]; /* high */
+ l = iptr->sx.s23.s2.tablelow;
+ i = iptr->sx.s23.s3.tablehigh;
- s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
+ s1 = emit_load_s1(jd, iptr, REG_ITMP1);
if (l == 0) {
M_INTMOVE(s1, REG_ITMP1);
}
- else if (l <= 4095) {
+ else if (-l >= 4096 && -l <= 4095) {
M_ADD_IMM(s1, -l, REG_ITMP1);
}
else {
ICONST(REG_ITMP2, l);
- /* XXX: do I need to truncate s1 to 32-bit ? */
M_SUB(s1, REG_ITMP2, REG_ITMP1);
}
- i = i - l + 1;
+
+ i = i - l + 1; /* number of targets (>0) */
/* 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, (basicblock *) tptr[0]);
- 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 */
- /* s4ptr += 3 + i; */
- tptr += i;
+ table += i;
while (--i >= 0) {
- /* dseg_addtarget(cd, BlockPtrOfPC(*--s4ptr)); */
- dseg_addtarget(cd, (basicblock *) tptr[0]);
- --tptr;
+ dseg_add_target(cd, table->block);
+ --table;
}
}
/* 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);
case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
{
- s4 i, /*l, */val, *s4ptr;
- void **tptr;
+ s4 i;
+ lookup_target_t *lookup;
- tptr = (void **) iptr->target;
+ lookup = iptr->dst.lookup;
- s4ptr = iptr->val.a;
- /*l = s4ptr[0];*/ /* default */
- i = s4ptr[1]; /* count */
+ i = iptr->sx.s23.s2.lookupcount;
MCODECHECK((i<<2)+8);
- s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
- while (--i >= 0) {
- s4ptr += 2;
- ++tptr;
+ s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- val = s4ptr[0];
- if ((val >= -4096) && (val <= 4095)) {
- M_CMP_IMM(s1, val);
+ while (--i >= 0) {
+ if ((lookup->value >= -4096) && (lookup->value <= 4095)) {
+ M_CMP_IMM(s1, lookup->value);
} else {
- ICONST(REG_ITMP2, val);
+ ICONST(REG_ITMP2, lookup->value);
M_CMP(s1, REG_ITMP2);
}
- M_BEQ(0);
- codegen_addreference(cd, (basicblock *) tptr[0]);
- M_NOP;
+ emit_beq(cd, lookup->target.block);
+ ++lookup;
}
- M_BR(0);
- tptr = (void **) iptr->target;
- codegen_addreference(cd, (basicblock *) tptr[0]);
- M_NOP;
+ emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
ALIGNCODENOP;
break;
}
case ICMD_BUILTIN: /* ..., arg1, arg2, arg3 ==> ... */
- /* op1 = arg count val.a = builtintable entry */
- bte = iptr->val.a;
+ bte = iptr->sx.s23.s3.bte;
md = bte->md;
+
+ /* XXX: builtin calling with stack arguments not implemented */
+ assert(md->paramcount <= 5 && md->argfltreguse <= 16);
+
+ s3 = md->paramcount;
+
+ MCODECHECK((s3 << 1) + 64);
+
+#ifdef BUILTIN_FLOAT_ARGS /* float args for builtins disabled */
+
+ /* copy float arguments according to ABI convention */
+
+ int num_fltregargs = 0;
+ int fltregarg_inswap[16];
+
+ for (s3 = s3 - 1; s3 >= 0; s3--) {
+ var = VAR(iptr->sx.s23.s2.args[s3]);
+
+ if (IS_FLT_DBL_TYPE(var->type)) {
+ if (!md->params[s3].inmemory) {
+ s1 = s3; /*native flt args use argument index directly*/
+ d = emit_load(jd, iptr, var, REG_FTMP1);
+
+ M_DMOV(d, s1 + 16);
+ fltregarg_inswap[num_fltregargs] = s1;
+ num_fltregargs++;
+ /*printf("builtin: flt arg swap to %d\n", s1 + 16);*/
+ }
+ else {
+ assert(0);
+ }
+ }
+ }
+
+ int i;
+ /* move swapped float args to target regs */
+ for (i = 0; i < num_fltregargs; i++) {
+ s1 = fltregarg_inswap[i];
+ M_DMOV(s1 + 16, s1);
+ /*printf("builtin float arg to target reg: %d ==> %d\n", s1+16, s1);*/
+ }
+
+#else
+ assert(md->argfltreguse == 0);
+#endif
+
goto gen_method;
case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
- /* op1 = arg count, val.a = method pointer */
case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
case ICMD_INVOKEINTERFACE:
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
- md = INSTRUCTION_UNRESOLVED_METHOD(iptr)->methodref->parseddesc.md;
lm = NULL;
+ um = iptr->sx.s23.s3.um;
+ md = um->methodref->parseddesc.md;
}
else {
- lm = INSTRUCTION_RESOLVED_METHODINFO(iptr);
+ lm = iptr->sx.s23.s3.fmiref->p.method;
+ um = NULL;
md = lm->parseddesc;
}
/* 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]);
+ d = md->params[s3].regoff;
+
+ 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, src, s1);
- M_INTMOVE(d, s1);
- } else {
- d = emit_load_s1(jd, iptr, src, REG_ITMP1);
- M_STX(d, REG_SP, md->params[s3].regoff * 8);
+ s1 = emit_load(jd, iptr, var, d);
+ M_INTMOVE(s1, d);
+ }
+ else {
+ s1 = emit_load(jd, iptr, var, REG_ITMP1);
+ M_STX(s1, REG_SP, JITSTACK + d);
}
-
- } else {
+ }
+ else {
+#ifdef BUILTIN_FLOAT_ARGS
+ if (iptr->opc == ICMD_BUILTIN)
+ continue;
+#endif
+
if (!md->params[s3].inmemory) {
- s1 = rd->argfltregs[md->params[s3].regoff];
- d = emit_load_s1(jd, iptr, src, s1);
- if (IS_2_WORD_TYPE(src->type))
- M_DMOV(d, s1);
- else
- M_FMOV(d, s1);
-
- } else {
- d = emit_load_s1(jd, iptr, src, REG_FTMP1);
- if (IS_2_WORD_TYPE(src->type))
- M_DST(d, REG_SP, md->params[s3].regoff * 8);
+ s1 = emit_load(jd, iptr, var, d);
+ if (IS_2_WORD_TYPE(var->type))
+ M_DMOV(s1, d);
else
- M_FST(d, REG_SP, md->params[s3].regoff * 8);
+ M_FMOV(s1, d);
+ }
+ else {
+ s1 = emit_load(jd, iptr, var, REG_FTMP1);
+ M_DST(s1, REG_SP, JITSTACK + d);
}
}
}
switch (iptr->opc) {
case ICMD_BUILTIN:
- disp = dseg_addaddress(cd, bte->fp);
- d = md->returntype.type;
-
- 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);*/
-
- /* if op1 == true, we need to check for an exception */
-
- if (iptr->op1 == true) {
- M_BEQZ(REG_RESULT_CALLER, 0);
- codegen_add_fillinstacktrace_ref(cd);
- M_NOP;
- }
- break;
+ disp = dseg_add_functionptr(cd, bte->fp);
+
+ 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);
+
+ emit_exception_check(cd, iptr);
+ if (md->returntype.type == TYPE_FLT) {
+ /* special handling for float return value in %f0 */
+ M_FMOV_INTERN(0,1);
+ }
+ break;
case ICMD_INVOKESPECIAL:
- M_BEQZ(rd->argintregs[0], 0);
- codegen_add_nullpointerexception_ref(cd);
- M_NOP;
- /* fall through */
+ emit_nullpointer_check(cd, iptr, REG_OUT0);
+ /* fall-through */
case ICMD_INVOKESTATIC:
if (lm == NULL) {
- unresolved_method *um = INSTRUCTION_UNRESOLVED_METHOD(iptr);
-
- 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;
- }
-
- d = um->methodref->parseddesc.md->returntype.type;
-
- } else {
- disp = dseg_addaddress(cd, lm->stubroutine);
- d = lm->parseddesc->returntype.type;
}
-
- 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 */
+ else
+ 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(rd->argintregs[0]);
+ emit_nullpointer_check(cd, iptr, REG_OUT0);
if (lm == NULL) {
- unresolved_method *um = INSTRUCTION_UNRESOLVED_METHOD(iptr);
-
- 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;
- d = um->methodref->parseddesc.md->returntype.type;
-
- } else {
+ }
+ else
s1 = OFFSET(vftbl_t, table[0]) +
sizeof(methodptr) * lm->vftblindex;
- d = lm->parseddesc->returntype.type;
- }
- M_ALD(REG_METHODPTR, rd->argintregs[0],
- OFFSET(java_objectheader, vftbl));
+ /* implicit null-pointer check */
+ M_ALD(REG_METHODPTR, REG_OUT0,OFFSET(java_object_t, 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:
- gen_nullptr_check(rd->argintregs[0]);
+ emit_nullpointer_check(cd, iptr, REG_OUT0);
if (lm == NULL) {
- unresolved_method *um = INSTRUCTION_UNRESOLVED_METHOD(iptr);
-
- 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;
- d = um->methodref->parseddesc.md->returntype.type;
-
- } else {
+ }
+ else {
s1 = OFFSET(vftbl_t, interfacetable[0]) -
sizeof(methodptr*) * lm->class->index;
s2 = sizeof(methodptr) * (lm - lm->class->methods);
-
- d = lm->parseddesc->returntype.type;
}
- M_ALD(REG_METHODPTR, rd->argintregs[0],
- OFFSET(java_objectheader, vftbl));
+ /* implicit null-pointer check */
+ M_ALD(REG_METHODPTR, REG_OUT0, OFFSET(java_object_t, 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(iptr->dst->type)) {
- s1 = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_RESULT_CALLER);
+ if (IS_INT_LNG_TYPE(d)) {
+ s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_CALLER);
M_INTMOVE(REG_RESULT_CALLER, s1);
- } else {
- s1 = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FRESULT);
- if (IS_2_WORD_TYPE(iptr->dst->type)) {
+ }
+ else {
+ s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
+ if (IS_2_WORD_TYPE(d)) {
M_DBLMOVE(REG_FRESULT, s1);
} else {
M_FLTMOVE(REG_FRESULT, s1);
}
}
- emit_store(jd, iptr, iptr->dst, s1);
+ emit_store_dst(jd, iptr, s1);
}
break;
case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
- /* op1: 0 == array, 1 == class */
/* val.a: (classinfo*) superclass */
/* superclass is an interface:
* super->vftbl->diffvall));
*/
- if (iptr->op1 == 1) {
+ if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
classinfo *super;
- vftbl_t *supervftbl;
s4 superindex;
- super = (classinfo *) iptr->val.a;
-
- 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)
- codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
-#endif
+ if ((super == NULL) || !(super->flags & ACC_INTERFACE))
+ CODEGEN_CRITICAL_SECTION_NEW;
- s1 = emit_load_s1(jd, iptr, src, 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);
+ s1 = emit_load_s1(jd, iptr, REG_ITMP1);
/* 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,
- (constant_classref *) iptr->target,
- 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,
- (constant_classref *) iptr->target,
- 0);
+ cr = iptr->sx.s23.s3.c.ref;
- if (opt_showdisassemble) {
- M_NOP; M_NOP;
- }
+ 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_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
+ 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,
- (constant_classref *) iptr->target,
- 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));
+ M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
M_ALD(REG_ITMP3, REG_PV, disp);
-#if defined(ENABLE_THREADS)
- codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
-#endif
+
+ CODEGEN_CRITICAL_SECTION_START;
+
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);
M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
-#if defined(ENABLE_THREADS)
- codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
-#endif
+
+ CODEGEN_CRITICAL_SECTION_END;
+
/* } */
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_var(rd, iptr->opc, iptr->dst, s1);
+ d = codegen_reg_of_dst(jd, iptr, s1);
}
else {
/* array type cast-check */
- s1 = emit_load_s1(jd, iptr, src, rd->argintregs[0]);
- M_INTMOVE(s1, rd->argintregs[0]);
+ s1 = emit_load_s1(jd, iptr, REG_OUT0);
+ M_INTMOVE(s1, REG_OUT0);
- disp = dseg_addaddress(cd, iptr->val.a);
+ disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
- if (iptr->val.a == NULL) {
- codegen_addpatchref(cd, PATCHER_builtin_arraycheckcast,
- (constant_classref *) iptr->target,
- disp);
+ if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+ 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);
+ M_ALD(REG_OUT1, REG_PV, disp);
+ 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, src, REG_ITMP1);
- M_BEQZ(REG_RESULT_CALLER, 0);
- codegen_add_classcastexception_ref(cd, s1);
- M_NOP;
+ s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+ emit_classcast_check(cd, iptr, ICMD_IFEQ, REG_RESULT_CALLER, s1);
- d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, s1);
+ d = codegen_reg_of_dst(jd, iptr, s1);
}
M_INTMOVE(s1, d);
- emit_store(jd, iptr, iptr->dst, d);
+ 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 ((super == NULL) || !(super->flags & ACC_INTERFACE))
+ CODEGEN_CRITICAL_SECTION_NEW;
+
+ 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_object_t, 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_object_t, vftbl));
+ M_ALD(REG_ITMP2, REG_PV, disp);
+
+ CODEGEN_CRITICAL_SECTION_START;
+
+ 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));
+
+ CODEGEN_CRITICAL_SECTION_END;
+
+ 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 */
+
+ MCODECHECK(64);
- /* copy values to interface registers */
+ /* At the end of a basic block we may have to append some nops,
+ because the patcher stub calling code might be longer than the
+ actual instruction. So codepatching does not change the
+ following block unintentionally. */
- 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_s1(jd, iptr, 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_s1(jd, iptr, 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 (cd->mcodeptr < cd->lastmcodeptr) {
+ while (cd->mcodeptr < cd->lastmcodeptr) {
+ M_NOP;
}
+ }
+
} /* if (bptr -> flags >= BBREACHED) */
} /* for basic block */
/* generate stubs */
- emit_exception_stubs(jd);
emit_patcher_stubs(jd);
- emit_replacement_stubs(jd);
-
- codegen_finish(jd);
/* everything's ok */
}
+/* codegen_emit_stub_compiler **************************************************
+ Emits a stub routine which calls the compiler.
+
+*******************************************************************************/
+void codegen_emit_stub_compiler(jitdata *jd)
+{
+ methodinfo *m;
+ codegendata *cd;
-/* createcompilerstub **********************************************************
+ /* get required compiler data */
- Creates a stub routine which calls the compiler.
-
-*******************************************************************************/
+ m = jd->m;
+ cd = jd->cd;
-#define COMPILERSTUB_DATASIZE 3 * SIZEOF_VOID_P
-#define COMPILERSTUB_CODESIZE 4 * 4
+ /* code for the stub */
-#define COMPILERSTUB_SIZE COMPILERSTUB_DATASIZE + COMPILERSTUB_CODESIZE
+ /* no window save yet, user caller's PV */
+ M_ALD_INTERN(REG_ITMP1, REG_PV_CALLER, -2 * SIZEOF_VOID_P); /* codeinfo pointer */
+ M_ALD_INTERN(REG_PV_CALLER, REG_PV_CALLER, -3 * SIZEOF_VOID_P); /* pointer to compiler */
+ M_JMP(REG_ZERO, REG_PV_CALLER, REG_ZERO); /* jump to the compiler, RA is wasted */
+ M_NOP;
+}
-u1 *createcompilerstub(methodinfo *m)
+/* codegen_emit_stub_native ****************************************************
+
+ Emits a stub routine which calls a native method.
+
+*******************************************************************************/
+
+void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
{
- u1 *s; /* memory to hold the stub */
- ptrint *d;
- codeinfo *code;
- codegendata *cd;
- s4 dumpsize;
-
- s = CNEW(u1, COMPILERSTUB_SIZE);
+ methodinfo *m;
+ codeinfo *code;
+ codegendata *cd;
+ methoddesc *md;
+ s4 nativeparams;
+ s4 i, j; /* count variables */
+ s4 t;
+ s4 s1, s2, disp;
+ s4 funcdisp; /* displacement of the function */
+ s4 fltregarg_offset[FLT_ARG_CNT];
- /* set data pointer and code pointer */
+ /* get required compiler data */
- d = (ptrint *) s;
- s = s + COMPILERSTUB_DATASIZE;
+ m = jd->m;
+ code = jd->code;
+ cd = jd->cd;
- /* mark start of dump memory area */
+ /* initialize variables */
- dumpsize = dump_size();
+ md = m->parseddesc;
+ nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
- cd = DNEW(codegendata);
- cd->mcodeptr = s;
-
- /* Store the codeinfo pointer in the same place as in the
- methodheader for compiled methods. */
+ /* calculate stack frame size */
- code = code_codeinfo_new(m);
+ cd->stackframesize =
+ sizeof(stackframeinfo) / SIZEOF_VOID_P +
+ sizeof(localref_table) / SIZEOF_VOID_P +
+ md->paramcount + /* for saving arguments over calls */
+ nmd->memuse + /* nmd->memuse includes the (6) abi params */
+ WINSAVE_CNT;
- d[0] = (ptrint) asm_call_jit_compiler;
- d[1] = (ptrint) m;
- d[2] = (ptrint) code;
- /* code for the stub */
- /* no window save yet, user caller's PV */
- M_ALD_INTERN(REG_ITMP1, REG_PV_CALLER, -2 * SIZEOF_VOID_P); /* codeinfo pointer */
- M_ALD_INTERN(REG_PV_CALLER, REG_PV_CALLER, -3 * SIZEOF_VOID_P); /* pointer to compiler */
- M_JMP(REG_ZERO, REG_PV_CALLER, REG_ZERO); /* jump to the compiler, RA is wasted */
- M_NOP;
+ /* keep stack 16-byte aligned (ABI requirement) */
+
+ if (cd->stackframesize & 1)
+ cd->stackframesize++;
+
+ /* 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 */
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- count_cstub_len += COMPILERSTUB_SIZE;
+ 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
- /* release dump area */
+ /* get function address (this must happen before the stackframeinfo) */
- dump_release(dumpsize);
+ funcdisp = dseg_add_functionptr(cd, f);
- return s;
-}
+#if !defined(WITH_STATIC_CLASSPATH)
+ if (f == NULL) {
+ codegen_add_patch_ref(cd, PATCHER_resolve_native, m, funcdisp);
+ }
+#endif
+
+ /* save float argument registers */
+ assert(ABIPARAMS_CNT >= FLT_ARG_CNT);
+ for (i = 0, j = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
+ if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
+ s1 = WINSAVE_CNT + nmd->memuse + j;
+ M_DST(abi_registers_float_argument[i], REG_SP, BIAS + (s1*8));
+ fltregarg_offset[i] = s1; /* remember stack offset */
+ j++;
+ }
+ }
+
+ /* prepare data structures for native function call */
+
+ M_ADD_IMM(REG_FP, BIAS, REG_OUT0); /* datasp == top of the stack frame (absolute, ie. + 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! */
+
+ /* keep float arguments on stack */
+#if 0
+ for (i = 0, j = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
+ if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
+ M_DLD(abi_registers_float_argument[i], REG_SP, CSTACK + (j * 8));
+ j++;
+ }
+ }
+#endif
-/* createnativestub ************************************************************
+ /* copy or spill arguments to new locations */
- Creates a stub routine which calls a native method.
+ for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
+ t = md->paramtypes[i].type;
-*******************************************************************************/
+ if (IS_INT_LNG_TYPE(t)) {
-u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
-{
- /* fabort("help me!"); */
- printf("createnativestub not implemented\n");
- return NULL;
+ /* integral types */
+
+ if (!md->params[i].inmemory) {
+ s1 = md->params[i].regoff;
+ /* s1 refers to the old window, transpose */
+ s1 = REG_WINDOW_TRANSPOSE(s1);
+
+ if (!nmd->params[j].inmemory) {
+ s2 = nmd->params[j].regoff;
+ M_INTMOVE(s1, s2);
+ } else {
+ /* nmd's regoff is relative to the start of the param array */
+ s2 = BIAS + WINSAVE_CNT * 8 + nmd->params[j].regoff;
+ M_AST(s1, REG_SP, s2);
+ }
+
+ } else {
+ if (!nmd->params[j].inmemory) {
+ /* JIT stack arg -> NAT reg arg */
+
+ /* Due to the Env pointer that is always passed, the 6th JIT arg */
+ /* is the 7th (or 8th w/ class ptr) NAT arg, and goes to the stack */
+
+ assert(false); /* path never taken */
+ }
+
+ s1 = md->params[i].regoff + cd->stackframesize * 8;
+ s2 = BIAS + WINSAVE_CNT * 8 + nmd->params[j].regoff;
+ M_ALD(REG_ITMP1, REG_SP, CSTACK + s1);
+ M_AST(REG_ITMP1, REG_SP, s2);
+ }
+
+ } else {
+
+ /* floating point types */
+
+ if (!md->params[i].inmemory) {
+ s1 = md->params[i].regoff;
+
+ if (!nmd->params[j].inmemory) {
+
+ /* no mapping to regs needed, native flt args use regoff */
+ s2 = nmd->params[j].regoff;
+
+ /* JIT float regs are still on the stack */
+ M_DLD(s2, REG_SP, BIAS + (fltregarg_offset[i] * 8));
+ }
+ else {
+ /* not supposed to happen with 16 NAT flt args */
+ assert(false);
+ /*
+ 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;
+
+ if (!nmd->params[j].inmemory) {
+
+ /* JIT stack -> NAT reg */
+
+ s2 = nmd->params[j].regoff;
+ M_DLD(s2, REG_FP, JITSTACK + s1);
+ }
+ else {
+
+ /* JIT stack -> NAT stack */
+
+ s2 = WINSAVE_CNT * 8 + nmd->params[j].regoff;
+
+ /* The FTMP register may already be loaded with args */
+ /* we know $f0 is unused because of the env pointer */
+ M_DLD(REG_F0, REG_FP, JITSTACK + s1);
+ M_DST(REG_F0, REG_SP, BIAS + s2);
+ }
+ }
+ }
+ }
+
+
+ /* 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;
+
+ /* handle exception */
+
+ disp = dseg_add_functionptr(cd, asm_handle_nat_exception);
+ M_ALD(REG_ITMP1, REG_PV, disp); /* load asm exception handler address */
+ M_MOV(REG_RA_CALLEE, REG_ITMP3_XPC); /* get exception address */
+ M_JMP(REG_ZERO, REG_ITMP1, REG_ZERO);/* jump to asm exception handler */
+ M_RESTORE(REG_ZERO, 0, REG_ZERO); /* restore callers window (DELAY) */
+
+ /* generate patcher stubs */
+
+ emit_patcher_stubs(jd);
}
/*