/* src/vm/jit/powerpc/codegen.c - machine code generator for 32-bit PowerPC
- 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
- Stefan Ring
- Christian Thalinger
- Christian Ullrich
- Edwin Steiner
-
- $Id: codegen.c 6156 2006-12-08 00:20:16Z edwin $
-
*/
#include "vm/jit/powerpc/codegen.h"
#include "mm/memory.h"
+
+#include "native/localref.h"
#include "native/native.h"
-#if defined(ENABLE_THREADS)
-# include "threads/native/lock.h"
-#endif
+#include "threads/lock-common.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/vm.h"
+
+#include "vm/jit/abi.h"
#include "vm/jit/abi-asm.h"
#include "vm/jit/asmpart.h"
#include "vm/jit/codegen-common.h"
#include "vm/jit/dseg.h"
#include "vm/jit/emit-common.h"
#include "vm/jit/jit.h"
+#include "vm/jit/md.h"
#include "vm/jit/methodheader.h"
#include "vm/jit/parse.h"
-#include "vm/jit/patcher.h"
+#include "vm/jit/patcher-common.h"
#include "vm/jit/reg.h"
#include "vm/jit/replace.h"
+#include "vm/jit/stacktrace.h"
#if defined(ENABLE_LSRA)
# include "vm/jit/allocator/lsra.h"
#endif
+#include "vmcore/loader.h"
+#include "vmcore/options.h"
+
/* codegen *********************************************************************
*******************************************************************************/
-bool codegen(jitdata *jd)
+bool codegen_emit(jitdata *jd)
{
methodinfo *m;
codeinfo *code;
/* space to save used callee saved registers */
savedregs_num += (INT_SAV_CNT - rd->savintreguse);
- savedregs_num += (FLT_SAV_CNT - rd->savfltreguse) * 2;
+ savedregs_num += (FLT_SAV_CNT - rd->savfltreguse);
cd->stackframesize = rd->memuse + savedregs_num;
not be shared with place to save the return register on PPC,
since both values reside in R3. */
- if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
- /* reserve 2 slots for long/double return values for monitorexit */
-
- if (IS_2_WORD_TYPE(m->parseddesc->returntype.type))
- cd->stackframesize += 3;
- else
- cd->stackframesize += 2;
- }
-
+ if (checksync && (m->flags & ACC_SYNCHRONIZED))
+ cd->stackframesize += 2;
#endif
/* create method header */
/* align stack to 16-bytes */
if (!jd->isleafmethod || JITDATA_HAS_FLAG_VERBOSECALL(jd))
- cd->stackframesize = (cd->stackframesize + 3) & ~3;
+ ALIGN_2(cd->stackframesize);
else if (jd->isleafmethod && (cd->stackframesize == LA_SIZE_IN_POINTERS))
cd->stackframesize = 0;
(void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
- (void) dseg_add_unique_s4(cd, cd->stackframesize * 4); /* FrameSize */
+ (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */
#if defined(ENABLE_THREADS)
/* IsSync contains the offset relative to the stack pointer for the
*/
if (checksync && (m->flags & ACC_SYNCHRONIZED))
- (void) dseg_add_unique_s4(cd, (rd->memuse + 1) * 4);/* IsSync */
+ (void) dseg_add_unique_s4(cd, (rd->memuse + 1) * 8);/* IsSync */
else
#endif
(void) dseg_add_unique_s4(cd, 0); /* IsSync */
dseg_add_target(cd, ex->handler);
(void) dseg_add_unique_address(cd, ex->catchtype.any);
}
-
+
+#if defined(ENABLE_PROFILING)
/* generate method profiling code */
if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
/* PROFILE_CYCLE_START; */
}
+#endif
/* create stack frame (if necessary) */
}
if (cd->stackframesize)
- M_STWU(REG_SP, REG_SP, -(cd->stackframesize * 4));
+ M_STWU(REG_SP, REG_SP, -(cd->stackframesize * 8));
/* save return address and used callee saved registers */
p = cd->stackframesize;
for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
- p--; M_IST(rd->savintregs[i], REG_SP, p * 4);
+ p--; M_IST(rd->savintregs[i], REG_SP, p * 8);
}
for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
- p -= 2; M_DST(rd->savfltregs[i], REG_SP, p * 4);
+ p--; M_DST(rd->savfltregs[i], REG_SP, p * 8);
}
/* take arguments out of register or stack frame */
continue;
var = VAR(varindex);
+ s1 = md->params[p].regoff;
- s1 = md->params[p].regoff;
- if (IS_INT_LNG_TYPE(t)) { /* integer args */
- if (IS_2_WORD_TYPE(t))
- s2 = PACK_REGS(rd->argintregs[GET_LOW_REG(s1)],
- rd->argintregs[GET_HIGH_REG(s1)]);
- else
- s2 = rd->argintregs[s1];
- if (!md->params[p].inmemory) { /* register arguments */
- if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
+ if (IS_INT_LNG_TYPE(t)) {
+ if (!md->params[p].inmemory) {
+ if (!IS_INMEMORY(var->flags)) {
if (IS_2_WORD_TYPE(t))
- M_LNGMOVE(s2, var->vv.regoff);
+ M_LNGMOVE(s1, var->vv.regoff);
else
- M_INTMOVE(s2, var->vv.regoff);
-
- } else { /* reg arg -> spilled */
+ M_INTMOVE(s1, var->vv.regoff);
+ }
+ else {
if (IS_2_WORD_TYPE(t))
- M_LST(s2, REG_SP, var->vv.regoff * 4);
+ M_LST(s1, REG_SP, var->vv.regoff);
else
- M_IST(s2, REG_SP, var->vv.regoff * 4);
+ M_IST(s1, REG_SP, var->vv.regoff);
}
-
- } else { /* stack arguments */
- if (!IS_INMEMORY(var->flags)) { /* stack arg -> register */
+ }
+ else {
+ if (!IS_INMEMORY(var->flags)) {
if (IS_2_WORD_TYPE(t))
- M_LLD(var->vv.regoff, REG_SP, (cd->stackframesize + s1) * 4);
+ M_LLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
else
- M_ILD(var->vv.regoff, REG_SP, (cd->stackframesize + s1) * 4);
-
- } else { /* stack arg -> spilled */
+ M_ILD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
+ }
+ else {
#if 1
- M_ILD(REG_ITMP1, REG_SP, (cd->stackframesize + s1) * 4);
- M_IST(REG_ITMP1, REG_SP, var->vv.regoff * 4);
+ M_ILD(REG_ITMP1, REG_SP, cd->stackframesize * 8 + s1);
+ M_IST(REG_ITMP1, REG_SP, var->vv.regoff);
if (IS_2_WORD_TYPE(t)) {
- M_ILD(REG_ITMP1, REG_SP, (cd->stackframesize + s1) * 4 +4);
- M_IST(REG_ITMP1, REG_SP, var->vv.regoff * 4 + 4);
+ M_ILD(REG_ITMP1, REG_SP, cd->stackframesize * 8 + s1 + 4);
+ M_IST(REG_ITMP1, REG_SP, var->vv.regoff + 4);
}
#else
/* Reuse Memory Position on Caller Stack */
- var->vv.regoff = cd->stackframesize + s1;
+ var->vv.regoff = cd->stackframesize * 8 + s1;
#endif
}
}
-
- } else { /* floating args */
- if (!md->params[p].inmemory) { /* register arguments */
- s2 = rd->argfltregs[s1];
- if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
- M_FLTMOVE(s2, var->vv.regoff);
-
- } else { /* reg arg -> spilled */
- if (IS_2_WORD_TYPE(t))
- M_DST(s2, REG_SP, var->vv.regoff * 4);
- else
- M_FST(s2, REG_SP, var->vv.regoff * 4);
- }
-
- } else { /* stack arguments */
- if (!IS_INMEMORY(var->flags)) { /* stack-arg -> register */
- if (IS_2_WORD_TYPE(t))
- M_DLD(var->vv.regoff, REG_SP, (cd->stackframesize + s1) * 4);
-
- else
- M_FLD(var->vv.regoff, REG_SP, (cd->stackframesize + s1) * 4);
-
- } else { /* stack-arg -> spilled */
+ }
+ else {
+ if (!md->params[p].inmemory) {
+ if (!IS_INMEMORY(var->flags))
+ M_FLTMOVE(s1, var->vv.regoff);
+ else
+ M_DST(s1, REG_SP, var->vv.regoff);
+ }
+ else {
+ if (!IS_INMEMORY(var->flags))
+ M_DLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
+ else {
#if 1
- if (IS_2_WORD_TYPE(t)) {
- M_DLD(REG_FTMP1, REG_SP, (cd->stackframesize + s1) * 4);
- M_DST(REG_FTMP1, REG_SP, var->vv.regoff * 4);
- var->vv.regoff = cd->stackframesize + s1;
-
- } else {
- M_FLD(REG_FTMP1, REG_SP, (cd->stackframesize + s1) * 4);
- M_FST(REG_FTMP1, REG_SP, var->vv.regoff * 4);
- }
+ M_DLD(REG_FTMP1, REG_SP, cd->stackframesize * 8 + s1);
+ M_DST(REG_FTMP1, REG_SP, var->vv.regoff);
#else
/* Reuse Memory Position on Caller Stack */
- var->vv.regoff = cd->stackframesize + s1;
+ var->vv.regoff = cd->stackframesize * 8 + s1;
#endif
}
}
}
- } /* end for */
+ }
#if defined(ENABLE_THREADS)
/* call monitorenter function */
M_AADD_IMM(REG_SP, -((LA_SIZE_IN_POINTERS + ARG_CNT) * 8), REG_SP);
for (p = 0; p < INT_ARG_CNT; p++)
- M_IST(rd->argintregs[p], REG_SP, LA_SIZE + p * 8);
+ M_IST(abi_registers_integer_argument[p], REG_SP, LA_SIZE + p * 8);
for (p = 0; p < FLT_ARG_CNT; p++)
- M_DST(rd->argfltregs[p], REG_SP, LA_SIZE + (INT_ARG_CNT + p) * 8);
+ M_DST(abi_registers_float_argument[p], REG_SP, LA_SIZE + (INT_ARG_CNT + p) * 8);
- /* ATTENTION: We multiply here with 2, because we use * 8
- above for simplicity and below * 4! */
-
- s1 += (LA_SIZE_IN_POINTERS + ARG_CNT) * 2;
+ s1 += LA_SIZE_IN_POINTERS + ARG_CNT;
}
# endif
- p = dseg_add_functionptr(cd, LOCK_monitor_enter);
- M_ALD(REG_ITMP3, REG_PV, p);
+ disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
+ M_ALD(REG_ITMP3, REG_PV, disp);
M_MTCTR(REG_ITMP3);
/* get or test the lock object */
if (m->flags & ACC_STATIC) {
- p = dseg_add_address(cd, &m->class->object.header);
- M_ALD(REG_A0, REG_PV, p);
+ disp = dseg_add_address(cd, &m->class->object.header);
+ M_ALD(REG_A0, REG_PV, disp);
}
else {
M_TST(REG_A0);
- M_BEQ(0);
- codegen_add_nullpointerexception_ref(cd);
+ M_BNE(1);
+ M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_NULLPOINTER);
}
- M_AST(REG_A0, REG_SP, s1 * 4);
+ M_AST(REG_A0, REG_SP, s1 * 8);
M_JSR;
# if !defined(NDEBUG)
if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
for (p = 0; p < INT_ARG_CNT; p++)
- M_ILD(rd->argintregs[p], REG_SP, LA_SIZE + p * 8);
+ M_ILD(abi_registers_integer_argument[p], REG_SP, LA_SIZE + p * 8);
for (p = 0; p < FLT_ARG_CNT; p++)
- M_DLD(rd->argfltregs[p], REG_SP, LA_SIZE + (INT_ARG_CNT + p) * 8);
+ M_DLD(abi_registers_float_argument[p], REG_SP, LA_SIZE + (INT_ARG_CNT + p) * 8);
M_AADD_IMM(REG_SP, (LA_SIZE_IN_POINTERS + ARG_CNT) * 8, REG_SP);
}
/* call trace function */
- if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
- emit_verbosecall_enter(jd);
+ emit_verbosecall_enter(jd);
}
/* end of header generation */
REPLACEMENT_POINT_BLOCK_START(cd, bptr);
+#if defined(ENABLE_PROFILING)
/* generate basicblock profiling code */
if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
/* if (bptr->type == BBTYPE_EXH) */
/* PROFILE_CYCLE_START; */
}
+#endif
/* copy interface registers to their destination */
case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- M_TST(s1);
- M_BEQ(0);
- codegen_add_nullpointerexception_ref(cd);
+ emit_nullpointer_check(cd, iptr, s1);
break;
/* constant operations ************************************************/
disp = dseg_add_unique_address(cd, cr);
- codegen_addpatchref(cd, PATCHER_resolve_classref_to_classinfo,
+ patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
cr, disp);
}
else
case ICMD_COPY:
case ICMD_MOVE:
- emit_copy(jd, iptr, VAROP(iptr->s1), VAROP(iptr->dst));
+ emit_copy(jd, iptr);
break;
case ICMD_ASTORE:
if (!(iptr->flags.bits & INS_FLAG_RETADDR))
- emit_copy(jd, iptr, VAROP(iptr->s1), VAROP(iptr->dst));
+ emit_copy(jd, iptr);
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_ITMP1);
- M_TST(s2);
- M_BEQ(0);
- codegen_add_arithmeticexception_ref(cd);
+ emit_arithmetic_check(cd, iptr, s2);
M_LDAH(REG_ITMP3, REG_ZERO, 0x8000);
M_CMP(REG_ITMP3, s1);
M_BNE(3 + (s1 != 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);
- M_TST(s2);
- M_BEQ(0);
- codegen_add_arithmeticexception_ref(cd);
+ emit_arithmetic_check(cd, iptr, s2);
M_LDAH(REG_ITMP3, REG_ZERO, 0x8000);
M_CMP(REG_ITMP3, s1);
M_BNE(4);
case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
- bte = iptr->sx.s23.s3.bte;
- md = bte->md;
+ s1 = emit_load_s1(jd, iptr, REG_A0_A1_PACKED);
+ s2 = emit_load_s2(jd, iptr, REG_A2_A3_PACKED);
- s2 = emit_load_s2(jd, iptr, REG_ITMP12_PACKED);
+ /* XXX TODO: only do this if arithmetic check is really done! */
M_OR_TST(GET_HIGH_REG(s2), GET_LOW_REG(s2), REG_ITMP3);
- M_BEQ(0);
- codegen_add_arithmeticexception_ref(cd);
+ /* XXX could be optimized */
+ emit_arithmetic_check(cd, iptr, REG_ITMP3);
+ bte = iptr->sx.s23.s3.bte;
disp = dseg_add_functionptr(cd, bte->fp);
M_ALD(REG_ITMP3, REG_PV, disp);
M_MTCTR(REG_ITMP3);
- s3 = PACK_REGS(rd->argintregs[GET_LOW_REG(md->params[1].regoff)],
- rd->argintregs[GET_HIGH_REG(md->params[1].regoff)]);
- M_LNGMOVE(s2, s3);
-
- s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
- s3 = PACK_REGS(rd->argintregs[GET_LOW_REG(md->params[0].regoff)],
- rd->argintregs[GET_HIGH_REG(md->params[0].regoff)]);
- M_LNGMOVE(s1, s3);
+ M_LNGMOVE(s1, REG_A0_A1_PACKED);
+ M_LNGMOVE(s2, REG_A2_A3_PACKED);
M_JSR;
s2 = emit_load_s2(jd, iptr, REG_FTMP2);
M_FCMPU(s1, s2);
M_BNAN(1);
- M_BEQ(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
+ emit_beq(cd, iptr->dst.block);
break;
case ICMD_IF_FCMPNE: /* ..., value, value ==> ... */
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
s2 = emit_load_s2(jd, iptr, REG_FTMP2);
M_FCMPU(s1, s2);
- M_BNAN(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
- M_BNE(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
+ emit_bnan(cd, iptr->dst.block);
+ emit_bne(cd, iptr->dst.block);
break;
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
s2 = emit_load_s2(jd, iptr, REG_FTMP2);
M_FCMPU(s1, s2);
- M_BNAN(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
- M_BLT(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
+ emit_bnan(cd, iptr->dst.block);
+ emit_blt(cd, iptr->dst.block);
break;
case ICMD_IF_FCMPL_GT: /* ..., value, value ==> ... */
s2 = emit_load_s2(jd, iptr, REG_FTMP2);
M_FCMPU(s1, s2);
M_BNAN(1);
- M_BGT(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
+ emit_bgt(cd, iptr->dst.block);
break;
case ICMD_IF_FCMPL_LE: /* ..., value, value ==> ... */
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
s2 = emit_load_s2(jd, iptr, REG_FTMP2);
M_FCMPU(s1, s2);
- M_BNAN(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
- M_BLE(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
+ emit_bnan(cd, iptr->dst.block);
+ emit_ble(cd, iptr->dst.block);
break;
case ICMD_IF_FCMPL_GE: /* ..., value, value ==> ... */
s2 = emit_load_s2(jd, iptr, REG_FTMP2);
M_FCMPU(s1, s2);
M_BNAN(1);
- M_BGE(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
+ emit_bge(cd, iptr->dst.block);
break;
case ICMD_IF_FCMPG_LT: /* ..., value, value ==> ... */
s2 = emit_load_s2(jd, iptr, REG_FTMP2);
M_FCMPU(s1, s2);
M_BNAN(1);
- M_BLT(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
+ emit_blt(cd, iptr->dst.block);
break;
case ICMD_IF_FCMPG_GT: /* ..., value, value ==> ... */
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
s2 = emit_load_s2(jd, iptr, REG_FTMP2);
M_FCMPU(s1, s2);
- M_BNAN(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
- M_BGT(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
+ emit_bnan(cd, iptr->dst.block);
+ emit_bgt(cd, iptr->dst.block);
break;
case ICMD_IF_FCMPG_LE: /* ..., value, value ==> ... */
s2 = emit_load_s2(jd, iptr, REG_FTMP2);
M_FCMPU(s1, s2);
M_BNAN(1);
- M_BLE(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
+ emit_ble(cd, iptr->dst.block);
break;
case ICMD_IF_FCMPG_GE: /* ..., value, value ==> ... */
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
s2 = emit_load_s2(jd, iptr, REG_FTMP2);
M_FCMPU(s1, s2);
- M_BNAN(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
- M_BGE(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
+ emit_bnan(cd, iptr->dst.block);
+ emit_bge(cd, iptr->dst.block);
break;
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
- emit_nullpointer_check(cd, s1);
- M_ILD(d, s1, OFFSET(java_arrayheader, size));
+ /* implicit null-pointer check */
+ 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);
- emit_array_checks(cd, iptr, s1, s2);
- M_IADD_IMM(s2, OFFSET(java_bytearray, data[0]), REG_ITMP2);
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
+ M_IADD_IMM(s2, OFFSET(java_bytearray_t, data[0]), REG_ITMP2);
+ /* implicit null-pointer check */
M_LBZX(d, s1, REG_ITMP2);
M_BSEXT(d, d);
emit_store_dst(jd, iptr, 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);
- emit_array_checks(cd, iptr, s1, s2);
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
M_SLL_IMM(s2, 1, REG_ITMP2);
- M_IADD_IMM(REG_ITMP2, OFFSET(java_chararray, data[0]), REG_ITMP2);
+ M_IADD_IMM(REG_ITMP2, OFFSET(java_chararray_t, data[0]), REG_ITMP2);
+ /* implicit null-pointer check */
M_LHZX(d, s1, REG_ITMP2);
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);
- emit_array_checks(cd, iptr, s1, s2);
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
M_SLL_IMM(s2, 1, REG_ITMP2);
- M_IADD_IMM(REG_ITMP2, OFFSET(java_shortarray, data[0]), REG_ITMP2);
+ M_IADD_IMM(REG_ITMP2, OFFSET(java_shortarray_t, data[0]), REG_ITMP2);
+ /* implicit null-pointer check */
M_LHAX(d, s1, REG_ITMP2);
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);
- emit_array_checks(cd, iptr, s1, s2);
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
M_SLL_IMM(s2, 2, REG_ITMP2);
- M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray, data[0]), REG_ITMP2);
+ M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray_t, data[0]), REG_ITMP2);
+ /* implicit null-pointer check */
M_LWZX(d, s1, REG_ITMP2);
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_ITMP12_PACKED);
- emit_array_checks(cd, iptr, s1, s2);
+ /* implicit null-pointer check */
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
M_SLL_IMM(s2, 3, REG_ITMP2);
M_IADD(s1, REG_ITMP2, REG_ITMP2);
- M_LLD_INTERN(d, REG_ITMP2, OFFSET(java_longarray, data[0]));
+ M_LLD_INTERN(d, REG_ITMP2, 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);
- emit_array_checks(cd, iptr, s1, s2);
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
M_SLL_IMM(s2, 2, REG_ITMP2);
- M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray, data[0]), REG_ITMP2);
+ M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray_t, data[0]), REG_ITMP2);
+ /* implicit null-pointer check */
M_LFSX(d, s1, REG_ITMP2);
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);
- emit_array_checks(cd, iptr, s1, s2);
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
M_SLL_IMM(s2, 3, REG_ITMP2);
- M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray, data[0]), REG_ITMP2);
+ M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray_t, data[0]), REG_ITMP2);
+ /* implicit null-pointer check */
M_LFDX(d, s1, REG_ITMP2);
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);
- emit_array_checks(cd, iptr, s1, s2);
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
M_SLL_IMM(s2, 2, REG_ITMP2);
- M_IADD_IMM(REG_ITMP2, OFFSET(java_objectarray, data[0]), REG_ITMP2);
+ M_IADD_IMM(REG_ITMP2, OFFSET(java_objectarray_t, data[0]), REG_ITMP2);
+ /* implicit null-pointer check */
M_LWZX(d, s1, REG_ITMP2);
emit_store_dst(jd, iptr, d);
break;
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- emit_array_checks(cd, iptr, s1, s2);
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
s3 = emit_load_s3(jd, iptr, REG_ITMP3);
- M_IADD_IMM(s2, OFFSET(java_bytearray, data[0]), REG_ITMP2);
+ M_IADD_IMM(s2, OFFSET(java_bytearray_t, data[0]), REG_ITMP2);
+ /* implicit null-pointer check */
M_STBX(s3, s1, REG_ITMP2);
break;
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- emit_array_checks(cd, iptr, s1, s2);
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
s3 = emit_load_s3(jd, iptr, REG_ITMP3);
M_SLL_IMM(s2, 1, REG_ITMP2);
- M_IADD_IMM(REG_ITMP2, OFFSET(java_chararray, data[0]), REG_ITMP2);
+ M_IADD_IMM(REG_ITMP2, OFFSET(java_chararray_t, data[0]), REG_ITMP2);
+ /* implicit null-pointer check */
M_STHX(s3, s1, REG_ITMP2);
break;
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- emit_array_checks(cd, iptr, s1, s2);
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
s3 = emit_load_s3(jd, iptr, REG_ITMP3);
M_SLL_IMM(s2, 1, REG_ITMP2);
- M_IADD_IMM(REG_ITMP2, OFFSET(java_shortarray, data[0]), REG_ITMP2);
+ M_IADD_IMM(REG_ITMP2, OFFSET(java_shortarray_t, data[0]), REG_ITMP2);
+ /* implicit null-pointer check */
M_STHX(s3, s1, REG_ITMP2);
break;
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- emit_array_checks(cd, iptr, s1, s2);
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
s3 = emit_load_s3(jd, iptr, REG_ITMP3);
M_SLL_IMM(s2, 2, REG_ITMP2);
- M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray, data[0]), REG_ITMP2);
+ M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray_t, data[0]), REG_ITMP2);
+ /* implicit null-pointer check */
M_STWX(s3, s1, REG_ITMP2);
break;
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- emit_array_checks(cd, iptr, s1, s2);
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
s3 = emit_load_s3_high(jd, iptr, REG_ITMP3);
M_SLL_IMM(s2, 3, REG_ITMP2);
- M_IADD_IMM(REG_ITMP2, OFFSET(java_longarray, data[0]), REG_ITMP2);
+ M_IADD_IMM(REG_ITMP2, OFFSET(java_longarray_t, data[0]), REG_ITMP2);
+ /* implicit null-pointer check */
M_STWX(s3, s1, REG_ITMP2);
M_IADD_IMM(REG_ITMP2, 4, REG_ITMP2);
s3 = emit_load_s3_low(jd, iptr, REG_ITMP3);
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- emit_array_checks(cd, iptr, s1, s2);
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
s3 = emit_load_s3(jd, iptr, REG_FTMP3);
M_SLL_IMM(s2, 2, REG_ITMP2);
- M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray, data[0]), REG_ITMP2);
+ M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray_t, data[0]), REG_ITMP2);
+ /* implicit null-pointer check */
M_STFSX(s3, s1, REG_ITMP2);
break;
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- emit_array_checks(cd, iptr, s1, s2);
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
s3 = emit_load_s3(jd, iptr, REG_FTMP3);
M_SLL_IMM(s2, 3, REG_ITMP2);
- M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray, data[0]), REG_ITMP2);
+ M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray_t, data[0]), REG_ITMP2);
+ /* implicit null-pointer check */
M_STFDX(s3, s1, REG_ITMP2);
break;
s1 = emit_load_s1(jd, iptr, REG_A0);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- emit_array_checks(cd, iptr, s1, s2);
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
s3 = emit_load_s3(jd, iptr, REG_A1);
- disp = dseg_add_functionptr(cd, BUILTIN_canstore);
+ /* XXX what if array is NULL */
+ disp = dseg_add_functionptr(cd, BUILTIN_FAST_canstore);
M_ALD(REG_ITMP3, REG_PV, disp);
M_MTCTR(REG_ITMP3);
M_INTMOVE(s3, REG_A1);
M_JSR;
- M_TST(REG_RESULT);
- M_BEQ(0);
- codegen_add_arraystoreexception_ref(cd);
+ emit_arraystore_check(cd, iptr);
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
s3 = emit_load_s3(jd, iptr, REG_ITMP3);
M_SLL_IMM(s2, 2, REG_ITMP2);
- M_IADD_IMM(REG_ITMP2, OFFSET(java_objectarray, data[0]), REG_ITMP2);
+ M_IADD_IMM(REG_ITMP2, OFFSET(java_objectarray_t, data[0]), REG_ITMP2);
+ /* implicit null-pointer check */
M_STWX(s3, s1, REG_ITMP2);
break;
fieldtype = uf->fieldref->parseddesc.fd->type;
disp = dseg_add_unique_address(cd, uf);
- codegen_addpatchref(cd, PATCHER_get_putstatic, uf, disp);
+ patcher_add_patch_ref(jd, 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_add_address(cd, fi->value);
if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
- codegen_addpatchref(cd, PATCHER_initialize_class,
+ patcher_add_patch_ref(jd, PATCHER_initialize_class,
fi->class, disp);
}
fieldtype = uf->fieldref->parseddesc.fd->type;
disp = dseg_add_unique_address(cd, uf);
- codegen_addpatchref(cd, PATCHER_get_putstatic, uf, disp);
+ patcher_add_patch_ref(jd, 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_add_address(cd, fi->value);
if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
- codegen_addpatchref(cd, PATCHER_initialize_class,
+ patcher_add_patch_ref(jd, PATCHER_initialize_class,
fi->class, disp);
}
case ICMD_GETFIELD: /* ... ==> ..., value */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- emit_nullpointer_check(cd, s1);
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
uf = iptr->sx.s23.s3.uf;
fieldtype = uf->fieldref->parseddesc.fd->type;
disp = 0;
- codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0);
+ patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
}
else {
fi = iptr->sx.s23.s3.fmiref->p.field;
disp = fi->offset;
}
+ /* implicit null-pointer check */
switch (fieldtype) {
case TYPE_INT:
d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
case ICMD_PUTFIELD: /* ..., value ==> ... */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- emit_nullpointer_check(cd, s1);
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
uf = iptr->sx.s23.s3.uf;
s2 = emit_load_s2(jd, iptr, REG_FTMP2);
if (INSTRUCTION_IS_UNRESOLVED(iptr))
- codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0);
+ patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
+ /* implicit null-pointer check */
switch (fieldtype) {
case TYPE_INT:
M_IST(s2, s1, disp);
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
unresolved_class *uc = iptr->sx.s23.s2.uc;
- codegen_addpatchref(cd, PATCHER_resolve_class, uc, 0);
+ patcher_add_patch_ref(jd, PATCHER_resolve_class, uc, 0);
}
#endif /* ENABLE_VERIFIER */
case ICMD_GOTO: /* ... ==> ... */
case ICMD_RET: /* ... ==> ... */
- M_BR(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
+ emit_br(cd, iptr->dst.block);
ALIGNCODENOP;
break;
case ICMD_JSR: /* ... ==> ... */
- M_BR(0);
- codegen_add_branch_ref(cd, iptr->sx.s23.s3.jsrtarget.block);
+ 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_TST(s1);
- M_BEQ(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
- break;
-
- case ICMD_IFNONNULL: /* ..., value ==> ... */
-
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- M_TST(s1);
- M_BNE(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
+ emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IFNULL, BRANCH_OPT_NONE);
break;
case ICMD_IFLT:
ICONST(REG_ITMP2, iptr->sx.val.i);
M_CMP(s1, REG_ITMP2);
}
- switch (iptr->opc) {
- case ICMD_IFLT:
- M_BLT(0);
- break;
- case ICMD_IFLE:
- M_BLE(0);
- break;
- case ICMD_IFNE:
- M_BNE(0);
- break;
- case ICMD_IFGT:
- M_BGT(0);
- break;
- case ICMD_IFGE:
- M_BGE(0);
- break;
- case ICMD_IFEQ:
- M_BEQ(0);
- break;
- }
- codegen_add_branch_ref(cd, iptr->dst.block);
+ emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IFEQ, BRANCH_OPT_NONE);
break;
M_XOR(s2, REG_ITMP3, REG_ITMP2);
M_OR_TST(REG_ITMP1, REG_ITMP2, REG_ITMP3);
}
- M_BEQ(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
+ emit_beq(cd, iptr->dst.block);
break;
case ICMD_IF_LLT: /* ..., value ==> ... */
+
s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
s2 = emit_load_s1_high(jd, iptr, REG_ITMP2);
if (iptr->sx.val.l == 0) {
/* if high word is less than zero, the whole long is too */
M_CMPI(s2, 0);
+ emit_blt(cd, iptr->dst.block);
}
else if ((iptr->sx.val.l >= 0) && (iptr->sx.val.l <= 0xffff)) {
M_CMPI(s2, 0);
- M_BLT(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
- M_BGT(2);
+ emit_blt(cd, iptr->dst.block);
+ emit_label_bgt(cd, BRANCH_LABEL_1);
M_CMPUI(s1, iptr->sx.val.l & 0xffff);
+ emit_blt(cd, iptr->dst.block);
+ emit_label(cd, BRANCH_LABEL_1);
}
else {
ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
M_CMP(s2, REG_ITMP3);
- M_BLT(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
- M_BGT(3);
+ emit_blt(cd, iptr->dst.block);
+ emit_label_bgt(cd, BRANCH_LABEL_1);
ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
M_CMPU(s1, REG_ITMP3);
+ emit_blt(cd, iptr->dst.block);
+ emit_label(cd, BRANCH_LABEL_1);
}
- M_BLT(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
break;
case ICMD_IF_LLE: /* ..., value ==> ... */
/* } else */
if ((iptr->sx.val.l >= 0) && (iptr->sx.val.l <= 0xffff)) {
M_CMPI(s2, 0);
- M_BLT(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
- M_BGT(2);
+ emit_blt(cd, iptr->dst.block);
+ emit_label_bgt(cd, BRANCH_LABEL_1);
M_CMPUI(s1, iptr->sx.val.l & 0xffff);
}
else {
ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
M_CMP(s2, REG_ITMP3);
- M_BLT(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
- M_BGT(3);
+ emit_blt(cd, iptr->dst.block);
+ emit_label_bgt(cd, BRANCH_LABEL_1);
ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
M_CMPU(s1, REG_ITMP3);
}
- M_BLE(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
+ emit_ble(cd, iptr->dst.block);
+ emit_label(cd, BRANCH_LABEL_1);
break;
case ICMD_IF_LNE: /* ..., value ==> ... */
M_XOR(s2, REG_ITMP3, REG_ITMP2);
M_OR_TST(REG_ITMP1, REG_ITMP2, REG_ITMP3);
}
- M_BNE(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
+ emit_bne(cd, iptr->dst.block);
break;
case ICMD_IF_LGT: /* ..., value ==> ... */
/* } else */
if ((iptr->sx.val.l >= 0) && (iptr->sx.val.l <= 0xffff)) {
M_CMPI(s2, 0);
- M_BGT(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
- M_BLT(2);
+ emit_bgt(cd, iptr->dst.block);
+ emit_label_blt(cd, BRANCH_LABEL_1);
M_CMPUI(s1, iptr->sx.val.l & 0xffff);
}
else {
ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
M_CMP(s2, REG_ITMP3);
- M_BGT(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
- M_BLT(3);
+ emit_bgt(cd, iptr->dst.block);
+ emit_label_blt(cd, BRANCH_LABEL_1);
ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
M_CMPU(s1, REG_ITMP3);
}
- M_BGT(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
+ emit_bgt(cd, iptr->dst.block);
+ emit_label(cd, BRANCH_LABEL_1);
break;
case ICMD_IF_LGE: /* ..., value ==> ... */
if (iptr->sx.val.l == 0) {
/* if high word is greater equal zero, the whole long is too */
M_CMPI(s2, 0);
+ emit_bge(cd, iptr->dst.block);
}
else if ((iptr->sx.val.l >= 0) && (iptr->sx.val.l <= 0xffff)) {
M_CMPI(s2, 0);
- M_BGT(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
- M_BLT(2);
+ emit_bgt(cd, iptr->dst.block);
+ emit_label_blt(cd, BRANCH_LABEL_1);
M_CMPUI(s1, iptr->sx.val.l & 0xffff);
+ emit_bge(cd, iptr->dst.block);
+ emit_label(cd, BRANCH_LABEL_1);
}
else {
ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
M_CMP(s2, REG_ITMP3);
- M_BGT(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
- M_BLT(3);
+ emit_bgt(cd, iptr->dst.block);
+ emit_label_blt(cd, BRANCH_LABEL_1);
ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
M_CMPU(s1, REG_ITMP3);
+ emit_bge(cd, iptr->dst.block);
+ emit_label(cd, BRANCH_LABEL_1);
}
- M_BGE(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
break;
case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
+ case ICMD_IF_ICMPNE:
+ case ICMD_IF_ICMPLT:
+ case ICMD_IF_ICMPGT:
+ case ICMD_IF_ICMPLE:
+ case ICMD_IF_ICMPGE:
+
+ s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+ s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+ M_CMP(s1, s2);
+ emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IF_ICMPEQ, BRANCH_OPT_NONE);
+ break;
+
case ICMD_IF_ACMPEQ: /* op1 = target JavaVM pc */
+ case ICMD_IF_ACMPNE:
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
M_CMP(s1, s2);
- M_BEQ(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
+ emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IF_ACMPEQ, BRANCH_OPT_NONE);
break;
case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
M_CMP(s1, s2);
- /* load low-bits before the branch, so we know the distance */
+ emit_label_bne(cd, BRANCH_LABEL_1);
s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
- M_BNE(2);
- M_CMP(s1, s2);
- M_BEQ(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
- break;
-
- case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
- case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
-
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- s2 = emit_load_s2(jd, iptr, REG_ITMP2);
M_CMP(s1, s2);
- M_BNE(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
+ emit_beq(cd, iptr->dst.block);
+ emit_label(cd, BRANCH_LABEL_1);
break;
case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
M_CMP(s1, s2);
- M_BNE(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
+ emit_bne(cd, iptr->dst.block);
s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
M_CMP(s1, s2);
- M_BNE(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
- break;
-
- case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
-
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- M_CMP(s1, s2);
- M_BLT(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
+ emit_bne(cd, iptr->dst.block);
break;
case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
M_CMP(s1, s2);
- M_BLT(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
- /* load low-bits before the branch, so we know the distance */
+ emit_blt(cd, iptr->dst.block);
+ emit_label_bgt(cd, BRANCH_LABEL_1);
s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
- M_BGT(2);
M_CMPU(s1, s2);
- M_BLT(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
- break;
-
- case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
-
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- M_CMP(s1, s2);
- M_BGT(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
+ emit_blt(cd, iptr->dst.block);
+ emit_label(cd, BRANCH_LABEL_1);
break;
case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
M_CMP(s1, s2);
- M_BGT(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
- /* load low-bits before the branch, so we know the distance */
+ emit_bgt(cd, iptr->dst.block);
+ emit_label_blt(cd, BRANCH_LABEL_1);
s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
- M_BLT(2);
M_CMPU(s1, s2);
- M_BGT(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
- break;
-
- case ICMD_IF_ICMPLE: /* ..., 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_add_branch_ref(cd, iptr->dst.block);
+ emit_bgt(cd, iptr->dst.block);
+ emit_label(cd, BRANCH_LABEL_1);
break;
case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
M_CMP(s1, s2);
- M_BLT(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
- /* load low-bits before the branch, so we know the distance */
+ emit_blt(cd, iptr->dst.block);
+ emit_label_bgt(cd, BRANCH_LABEL_1);
s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
- M_BGT(2);
M_CMPU(s1, s2);
- M_BLE(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
- break;
-
- case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
-
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- M_CMP(s1, s2);
- M_BGE(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
+ emit_ble(cd, iptr->dst.block);
+ emit_label(cd, BRANCH_LABEL_1);
break;
case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
M_CMP(s1, s2);
- M_BGT(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
- /* load low-bits before the branch, so we know the distance */
+ emit_bgt(cd, iptr->dst.block);
+ emit_label_blt(cd, BRANCH_LABEL_1);
s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
- M_BLT(2);
M_CMPU(s1, s2);
- M_BGE(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
+ emit_bge(cd, iptr->dst.block);
+ emit_label(cd, BRANCH_LABEL_1);
break;
case ICMD_IRETURN: /* ..., retvalue ==> ... */
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
unresolved_class *uc = iptr->sx.s23.s2.uc;
- codegen_addpatchref(cd, PATCHER_resolve_class, uc, 0);
+ patcher_add_patch_ref(jd, PATCHER_resolve_class, uc, 0);
}
#endif /* ENABLE_VERIFIER */
goto nowperformreturn;
/* call trace function */
- if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
- emit_verbosecall_exit(jd);
+ emit_verbosecall_exit(jd);
#if defined(ENABLE_THREADS)
if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
switch (iptr->opc) {
case ICMD_LRETURN:
- M_IST(REG_RESULT2, REG_SP, rd->memuse * 4 + 8);
+ M_IST(REG_RESULT2, REG_SP, rd->memuse * 8 + 8);
/* fall through */
case ICMD_IRETURN:
case ICMD_ARETURN:
- M_IST(REG_RESULT , REG_SP, rd->memuse * 4 + 4);
+ M_IST(REG_RESULT , REG_SP, rd->memuse * 8 + 4);
break;
case ICMD_FRETURN:
- M_FST(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
- break;
case ICMD_DRETURN:
- M_DST(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
+ M_DST(REG_FRESULT, REG_SP, rd->memuse * 8 + 4);
break;
}
- M_ALD(REG_A0, REG_SP, rd->memuse * 4);
+ M_ALD(REG_A0, REG_SP, rd->memuse * 8);
M_JSR;
/* and now restore the proper return value */
switch (iptr->opc) {
case ICMD_LRETURN:
- M_ILD(REG_RESULT2, REG_SP, rd->memuse * 4 + 8);
+ M_ILD(REG_RESULT2, REG_SP, rd->memuse * 8 + 8);
/* fall through */
case ICMD_IRETURN:
case ICMD_ARETURN:
- M_ILD(REG_RESULT , REG_SP, rd->memuse * 4 + 4);
+ M_ILD(REG_RESULT , REG_SP, rd->memuse * 8 + 4);
break;
case ICMD_FRETURN:
- M_FLD(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
- break;
case ICMD_DRETURN:
- M_DLD(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
+ M_DLD(REG_FRESULT, REG_SP, rd->memuse * 8 + 4);
break;
}
}
/* ATTENTION: Don't use REG_ZERO (r0) here, as M_ALD
may have a displacement overflow. */
- M_ALD(REG_ITMP1, REG_SP, p * 4 + LA_LR_OFFSET);
+ M_ALD(REG_ITMP1, REG_SP, p * 8 + LA_LR_OFFSET);
M_MTLR(REG_ITMP1);
}
/* restore saved registers */
for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
- p--; M_ILD(rd->savintregs[i], REG_SP, p * 4);
+ p--; M_ILD(rd->savintregs[i], REG_SP, p * 8);
}
for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
- p -= 2; M_DLD(rd->savfltregs[i], REG_SP, p * 4);
+ p--; M_DLD(rd->savfltregs[i], REG_SP, p * 8);
}
/* deallocate stack */
if (cd->stackframesize)
- M_LDA(REG_SP, REG_SP, cd->stackframesize * 4);
+ M_LDA(REG_SP, REG_SP, cd->stackframesize * 8);
M_RET;
ALIGNCODENOP;
/* range check */
M_CMPUI(REG_ITMP1, i - 1);
- M_BGT(0);
- codegen_add_branch_ref(cd, table[0].block);
+ emit_bgt(cd, table[0].block);
/* build jump table top down and use address of lowest entry */
M_ILD(REG_ITMP2, REG_PV, disp);
M_CMP(s1, REG_ITMP2);
}
- M_BEQ(0);
- codegen_add_branch_ref(cd, lookup->target.block);
+ emit_beq(cd, lookup->target.block);
lookup++;
}
- M_BR(0);
- codegen_add_branch_ref(cd, iptr->sx.s23.s3.lookupdefault.block);
-
+ emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
ALIGNCODENOP;
break;
}
for (s3 = s3 - 1; s3 >= 0; s3--) {
var = VAR(iptr->sx.s23.s2.args[s3]);
+ d = md->params[s3].regoff;
/* Already Preallocated? */
if (var->flags & PREALLOC)
if (IS_INT_LNG_TYPE(var->type)) {
if (!md->params[s3].inmemory) {
if (IS_2_WORD_TYPE(var->type)) {
- s1 = PACK_REGS(
- rd->argintregs[GET_LOW_REG(md->params[s3].regoff)],
- rd->argintregs[GET_HIGH_REG(md->params[s3].regoff)]);
- d = emit_load(jd, iptr, var, s1);
- M_LNGMOVE(d, s1);
+ s1 = emit_load(jd, iptr, var, d);
+ M_LNGMOVE(s1, d);
}
else {
- s1 = rd->argintregs[md->params[s3].regoff];
- d = emit_load(jd, iptr, var, s1);
- M_INTMOVE(d, s1);
+ s1 = emit_load(jd, iptr, var, d);
+ M_INTMOVE(s1, d);
}
}
else {
if (IS_2_WORD_TYPE(var->type)) {
- d = emit_load(jd, iptr, var, REG_ITMP12_PACKED);
- M_LST(d, REG_SP, md->params[s3].regoff * 4);
+ s1 = emit_load(jd, iptr, var, REG_ITMP12_PACKED);
+ M_LST(s1, REG_SP, d);
}
else {
- d = emit_load(jd, iptr, var, REG_ITMP1);
- M_IST(d, REG_SP, md->params[s3].regoff * 4);
+ s1 = emit_load(jd, iptr, var, REG_ITMP1);
+ M_IST(s1, REG_SP, d);
}
}
}
else {
if (!md->params[s3].inmemory) {
- s1 = rd->argfltregs[md->params[s3].regoff];
- d = emit_load(jd, iptr, var, s1);
- M_FLTMOVE(d, s1);
+ s1 = emit_load(jd, iptr, var, d);
+ M_FLTMOVE(s1, d);
}
else {
- d = emit_load(jd, iptr, var, REG_FTMP1);
- if (IS_2_WORD_TYPE(var->type))
- M_DST(d, REG_SP, md->params[s3].regoff * 4);
- else
- M_FST(d, REG_SP, md->params[s3].regoff * 4);
+ s1 = emit_load(jd, iptr, var, REG_FTMP1);
+ M_DST(s1, REG_SP, d);
}
}
}
disp = dseg_add_functionptr(cd, bte->fp);
M_ALD(REG_PV, REG_PV, disp); /* pointer to built-in-function */
+
+ /* generate the actual call */
+
+ M_MTCTR(REG_PV);
+ M_JSR;
+ REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
+ disp = (s4) (cd->mcodeptr - cd->mcodebase);
+ M_MFLR(REG_ITMP1);
+ M_LDA(REG_PV, REG_ITMP1, -disp);
+
+ emit_exception_check(cd, iptr);
break;
case ICMD_INVOKESPECIAL:
- emit_nullpointer_check(cd, REG_A0);
- M_ILD(REG_ITMP1, REG_A0, 0); /* hardware nullptr */
- /* fall through */
+ emit_nullpointer_check(cd, iptr, REG_A0);
+ /* fall-through */
case ICMD_INVOKESTATIC:
if (lm == NULL) {
disp = dseg_add_unique_address(cd, um);
- codegen_addpatchref(cd, PATCHER_invokestatic_special,
+ patcher_add_patch_ref(jd, PATCHER_invokestatic_special,
um, disp);
}
else
disp = dseg_add_address(cd, lm->stubroutine);
M_ALD(REG_PV, REG_PV, disp);
+
+ /* generate the actual call */
+
+ M_MTCTR(REG_PV);
+ M_JSR;
+ REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
+ disp = (s4) (cd->mcodeptr - cd->mcodebase);
+ M_MFLR(REG_ITMP1);
+ M_LDA(REG_PV, REG_ITMP1, -disp);
break;
case ICMD_INVOKEVIRTUAL:
- emit_nullpointer_check(cd, REG_A0);
-
if (lm == NULL) {
- codegen_addpatchref(cd, PATCHER_invokevirtual, um, 0);
+ patcher_add_patch_ref(jd, PATCHER_invokevirtual, um, 0);
s1 = 0;
}
sizeof(methodptr) * lm->vftblindex;
}
- M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_objectheader, vftbl));
+ /* implicit null-pointer check */
+ M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
M_ALD(REG_PV, REG_METHODPTR, s1);
+
+ /* generate the actual call */
+
+ M_MTCTR(REG_PV);
+ M_JSR;
+ REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
+ disp = (s4) (cd->mcodeptr - cd->mcodebase);
+ M_MFLR(REG_ITMP1);
+ M_LDA(REG_PV, REG_ITMP1, -disp);
break;
case ICMD_INVOKEINTERFACE:
- emit_nullpointer_check(cd, REG_A0);
-
if (lm == NULL) {
- codegen_addpatchref(cd, PATCHER_invokeinterface, um, 0);
+ patcher_add_patch_ref(jd, PATCHER_invokeinterface, um, 0);
s1 = 0;
s2 = 0;
s2 = sizeof(methodptr) * (lm - lm->class->methods);
}
- M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_objectheader, vftbl));
+ /* implicit null-pointer check */
+ M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
M_ALD(REG_PV, REG_METHODPTR, s2);
- break;
- }
-
- /* generate the actual call */
- M_MTCTR(REG_PV);
- M_JSR;
- REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
- disp = (s4) (cd->mcodeptr - cd->mcodebase);
- M_MFLR(REG_ITMP1);
- M_LDA(REG_PV, REG_ITMP1, -disp);
-
- /* actually only used for ICMD_BUILTIN */
+ /* generate the actual call */
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- M_CMPI(REG_RESULT, 0);
- M_BEQ(0);
- codegen_add_fillinstacktrace_ref(cd);
+ M_MTCTR(REG_PV);
+ M_JSR;
+ REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
+ disp = (s4) (cd->mcodeptr - cd->mcodebase);
+ M_MFLR(REG_ITMP1);
+ M_LDA(REG_PV, REG_ITMP1, -disp);
+ break;
}
/* store return value */
case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
- /* val.a: (classinfo*) superclass */
-
- /* superclass is an interface:
- *
- * OK if ((sub == NULL) ||
- * (sub->vftbl->interfacetablelength > super->index) &&
- * (sub->vftbl->interfacetable[-super->index] != NULL));
- *
- * superclass is a class:
- *
- * OK if ((sub == NULL) || (0
- * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
- * super->vftbl->diffvall));
- */
if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
/* object type cast-check */
s4 superindex;
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
- super = NULL;
+ super = NULL;
superindex = 0;
}
else {
- super = iptr->sx.s23.s3.c.cls;
+ super = iptr->sx.s23.s3.c.cls;
superindex = super->index;
}
-
-#if defined(ENABLE_THREADS)
- codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
-#endif
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
-
- /* calculate interface checkcast code size */
-
- s2 = 7;
- if (super == NULL)
- s2 += (opt_shownops ? 1 : 0);
+ if ((super == NULL) || !(super->flags & ACC_INTERFACE))
+ CODEGEN_CRITICAL_SECTION_NEW;
- /* calculate class checkcast code size */
-
- s3 = 8 + (s1 == REG_ITMP1);
- if (super == NULL)
- s3 += (opt_shownops ? 1 : 0);
+ s1 = emit_load_s1(jd, iptr, REG_ITMP1);
/* if class is not resolved, check which code to call */
if (super == NULL) {
M_TST(s1);
- M_BEQ(3 + (opt_shownops ? 1 : 0) + s2 + 1 + s3);
+ emit_label_beq(cd, BRANCH_LABEL_1);
disp = dseg_add_unique_s4(cd, 0); /* super->flags */
- codegen_addpatchref(cd,
+ patcher_add_patch_ref(jd,
PATCHER_resolve_classref_to_flags,
iptr->sx.s23.s3.c.ref,
disp);
M_ILD(REG_ITMP2, REG_PV, disp);
M_AND_IMM(REG_ITMP2, ACC_INTERFACE, REG_ITMP2);
- M_BEQ(s2 + 1);
+ emit_label_beq(cd, BRANCH_LABEL_2);
}
/* interface checkcast code */
if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
if (super == NULL) {
- codegen_addpatchref(cd,
- PATCHER_checkcast_instanceof_interface,
+ patcher_add_patch_ref(jd,
+ PATCHER_checkcast_interface,
iptr->sx.s23.s3.c.ref,
0);
}
else {
M_TST(s1);
- M_BEQ(s2);
+ emit_label_beq(cd, BRANCH_LABEL_3);
}
- M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
+ M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
M_LDATST(REG_ITMP3, REG_ITMP3, -superindex);
- M_BLE(0);
- codegen_add_classcastexception_ref(cd, s1);
+ emit_classcast_check(cd, iptr, BRANCH_LE, REG_ITMP3, s1);
+
M_ALD(REG_ITMP3, REG_ITMP2,
OFFSET(vftbl_t, interfacetable[0]) -
superindex * sizeof(methodptr*));
M_TST(REG_ITMP3);
- M_BEQ(0);
- codegen_add_classcastexception_ref(cd, s1);
+ emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ITMP3, s1);
if (super == NULL)
- M_BR(s3);
+ 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);
+
disp = dseg_add_unique_address(cd, NULL);
- codegen_addpatchref(cd, PATCHER_resolve_classref_to_vftbl,
+ patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_vftbl,
iptr->sx.s23.s3.c.ref,
disp);
}
disp = dseg_add_address(cd, super->vftbl);
M_TST(s1);
- M_BEQ(s3);
+ emit_label_beq(cd, BRANCH_LABEL_5);
}
- M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
-#if defined(ENABLE_THREADS)
- codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
-#endif
+ M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
+
+ CODEGEN_CRITICAL_SECTION_START;
+
M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
M_ALD(REG_ITMP2, REG_PV, disp);
if (s1 != REG_ITMP1) {
M_ILD(REG_ITMP1, REG_ITMP2, OFFSET(vftbl_t, baseval));
M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
-#if defined(ENABLE_THREADS)
- codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
-#endif
+
+ CODEGEN_CRITICAL_SECTION_END;
+
M_ISUB(REG_ITMP3, REG_ITMP1, REG_ITMP3);
- } else {
+ }
+ else {
M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
M_ISUB(REG_ITMP3, REG_ITMP2, REG_ITMP3);
M_ALD(REG_ITMP2, REG_PV, disp);
M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
-#if defined(ENABLE_THREADS)
- codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
-#endif
+
+ CODEGEN_CRITICAL_SECTION_END;
}
M_CMPU(REG_ITMP3, REG_ITMP2);
- M_BGT(0);
- codegen_add_classcastexception_ref(cd, s1);
+ emit_classcast_check(cd, iptr, BRANCH_GT, REG_ITMP3, s1);
+
+ if (super != NULL)
+ emit_label(cd, BRANCH_LABEL_5);
}
+
+ if (super == NULL) {
+ emit_label(cd, BRANCH_LABEL_1);
+ emit_label(cd, BRANCH_LABEL_4);
+ }
+
d = codegen_reg_of_dst(jd, iptr, s1);
}
else {
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
disp = dseg_add_unique_address(cd, NULL);
- codegen_addpatchref(cd, PATCHER_resolve_classref_to_classinfo,
+ patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
iptr->sx.s23.s3.c.ref,
disp);
}
M_MTCTR(REG_ITMP2);
M_JSR;
M_TST(REG_RESULT);
- M_BEQ(0);
- codegen_add_classcastexception_ref(cd, s1);
+ emit_classcast_check(cd, iptr, BRANCH_EQ, REG_RESULT, s1);
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
d = codegen_reg_of_dst(jd, iptr, s1);
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;
s4 superindex;
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
- super = NULL;
+ super = NULL;
superindex = 0;
}
else {
- super = iptr->sx.s23.s3.c.cls;
+ super = iptr->sx.s23.s3.c.cls;
superindex = super->index;
}
-#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, REG_ITMP1);
+
d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
if (s1 == d) {
M_MOV(s1, REG_ITMP1);
s1 = REG_ITMP1;
}
- /* calculate interface instanceof code size */
-
- s2 = 8;
- if (super == NULL)
- s2 += (opt_shownops ? 1 : 0);
-
- /* calculate class instanceof code size */
-
- s3 = 10;
- if (super == NULL)
- s3 += (opt_shownops ? 1 : 0);
-
M_CLR(d);
/* if class is not resolved, check which code to call */
if (super == NULL) {
M_TST(s1);
- M_BEQ(3 + (opt_shownops ? 1 : 0) + s2 + 1 + s3);
+ emit_label_beq(cd, BRANCH_LABEL_1);
disp = dseg_add_unique_s4(cd, 0); /* super->flags */
- codegen_addpatchref(cd, PATCHER_resolve_classref_to_flags,
+ patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
iptr->sx.s23.s3.c.ref, disp);
M_ILD(REG_ITMP3, REG_PV, disp);
M_AND_IMM(REG_ITMP3, ACC_INTERFACE, REG_ITMP3);
- M_BEQ(s2 + 1);
+ emit_label_beq(cd, BRANCH_LABEL_2);
}
/* interface instanceof code */
if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
if (super == NULL) {
- codegen_addpatchref(cd,
- PATCHER_checkcast_instanceof_interface,
+ patcher_add_patch_ref(jd,
+ PATCHER_instanceof_interface,
iptr->sx.s23.s3.c.ref, 0);
}
else {
M_TST(s1);
- M_BEQ(s2);
+ emit_label_beq(cd, BRANCH_LABEL_3);
}
- M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
+ M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
M_LDATST(REG_ITMP3, REG_ITMP3, -superindex);
M_BLE(4);
M_IADD_IMM(REG_ZERO, 1, d);
if (super == NULL)
- M_BR(s3);
+ 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);
+
disp = dseg_add_unique_address(cd, NULL);
- codegen_addpatchref(cd, PATCHER_resolve_classref_to_vftbl,
+ patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_vftbl,
iptr->sx.s23.s3.c.ref,
disp);
}
disp = dseg_add_address(cd, super->vftbl);
M_TST(s1);
- M_BEQ(s3);
+ emit_label_beq(cd, BRANCH_LABEL_5);
}
- M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
+ M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
M_ALD(REG_ITMP2, REG_PV, disp);
-#if defined(ENABLE_THREADS)
- codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
-#endif
+
+ 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));
-#if defined(ENABLE_THREADS)
- codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
-#endif
+
+ CODEGEN_CRITICAL_SECTION_END;
+
M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
M_CMPU(REG_ITMP1, REG_ITMP2);
M_CLR(d);
M_BGT(1);
M_IADD_IMM(REG_ZERO, 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;
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
disp = dseg_add_unique_address(cd, NULL);
- codegen_addpatchref(cd, PATCHER_resolve_classref_to_classinfo,
+ patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
iptr->sx.s23.s3.c.ref, disp);
}
else
/* check for exception before result assignment */
- M_CMPI(REG_RESULT, 0);
- M_BEQ(0);
- codegen_add_fillinstacktrace_ref(cd);
+ emit_exception_check(cd, iptr);
d = codegen_reg_of_dst(jd, iptr, REG_RESULT);
M_INTMOVE(REG_RESULT, d);
break;
default:
- *exceptionptr =
- new_internalerror("Unknown ICMD %d during code generation",
- iptr->opc);
+ exceptions_throw_internalerror("Unknown ICMD %d during code generation",
+ iptr->opc);
return false;
} /* switch */
dseg_createlinenumbertable(cd);
- /* generate stubs */
-
- emit_exception_stubs(jd);
- emit_patcher_stubs(jd);
- REPLACEMENT_EMIT_STUBS(jd);
+ /* generate traps */
- codegen_finish(jd);
+ emit_patcher_traps(jd);
/* everything's ok */
}
-/* createcompilerstub **********************************************************
+/* codegen_emit_stub_compiler **************************************************
- Creates a stub routine which calls the compiler.
+ Emits a stub routine which calls the compiler.
*******************************************************************************/
-#define COMPILERSTUB_DATASIZE 3 * SIZEOF_VOID_P
-#define COMPILERSTUB_CODESIZE 4 * 4
-
-#define COMPILERSTUB_SIZE COMPILERSTUB_DATASIZE + COMPILERSTUB_CODESIZE
-
-
-u1 *createcompilerstub(methodinfo *m)
+void codegen_emit_stub_compiler(jitdata *jd)
{
- u1 *s; /* memory to hold the stub */
- ptrint *d;
+ methodinfo *m;
codegendata *cd;
- s4 dumpsize;
-
- s = CNEW(u1, COMPILERSTUB_SIZE);
- /* set data pointer and code pointer */
-
- d = (ptrint *) s;
- s = s + COMPILERSTUB_DATASIZE;
-
- /* mark start of dump memory area */
-
- dumpsize = dump_size();
-
- cd = DNEW(codegendata);
- cd->mcodeptr = s;
+ /* get required compiler data */
- /* The codeinfo pointer is actually a pointer to the
- methodinfo. This fakes a codeinfo structure. */
+ m = jd->m;
+ cd = jd->cd;
- d[0] = (ptrint) asm_call_jit_compiler;
- d[1] = (ptrint) m;
- d[2] = (ptrint) &d[1]; /* fake code->m */
+ /* code for the stub */
M_ALD_INTERN(REG_ITMP1, REG_PV, -2 * SIZEOF_VOID_P);
M_ALD_INTERN(REG_PV, REG_PV, -3 * SIZEOF_VOID_P);
M_MTCTR(REG_PV);
M_RTS;
-
- md_cacheflush((u1 *) d, COMPILERSTUB_SIZE);
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- count_cstub_len += COMPILERSTUB_SIZE;
-#endif
-
- /* release dump area */
-
- dump_release(dumpsize);
-
- return s;
}
-/* createnativestub ************************************************************
+/* codegen_emit_stub_native ****************************************************
- Creates a stub routine which calls a native method.
+ Emits a stub routine which calls a native method.
*******************************************************************************/
-u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
+void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
{
- methodinfo *m;
- codeinfo *code;
- codegendata *cd;
- registerdata *rd;
- methoddesc *md;
- s4 nativeparams;
- s4 i, j; /* count variables */
- s4 t;
- s4 s1, s2, disp;
- s4 funcdisp;
+ methodinfo *m;
+ codeinfo *code;
+ codegendata *cd;
+ methoddesc *md;
+ s4 nativeparams;
+ s4 i, j; /* count variables */
+ s4 t;
+ s4 s1, s2, disp;
+ s4 funcdisp;
/* get required compiler data */
m = jd->m;
code = jd->code;
cd = jd->cd;
- rd = jd->rd;
/* set some variables */
/* create method header */
(void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
- (void) dseg_add_unique_s4(cd, cd->stackframesize * 4); /* FrameSize */
+ (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */
(void) dseg_add_unique_s4(cd, 0); /* IsSync */
(void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
(void) dseg_add_unique_s4(cd, 0); /* IntSave */
M_MFLR(REG_ZERO);
M_AST_INTERN(REG_ZERO, REG_SP, LA_LR_OFFSET);
- M_STWU(REG_SP, REG_SP, -(cd->stackframesize * 4));
-
- if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
- emit_verbosecall_enter(jd);
+ M_STWU(REG_SP, REG_SP, -(cd->stackframesize * 8));
/* get function address (this must happen before the stackframeinfo) */
#if !defined(WITH_STATIC_CLASSPATH)
if (f == NULL)
- codegen_addpatchref(cd, PATCHER_resolve_native_function, m, funcdisp);
+ patcher_add_patch_ref(jd, PATCHER_resolve_native_function, m, funcdisp);
#endif
- /* save integer and float argument registers */
+ /* emit trace code */
- j = 0;
+ emit_verbosecall_enter(jd);
- for (i = 0; i < md->paramcount; i++) {
- t = md->paramtypes[i].type;
+#if defined(ENABLE_GC_CACAO)
+ /* Save callee saved integer registers in stackframeinfo (GC may
+ need to recover them during a collection). */
- if (IS_INT_LNG_TYPE(t)) {
- if (!md->params[i].inmemory) {
- s1 = md->params[i].regoff;
- if (IS_2_WORD_TYPE(t)) {
- M_IST(rd->argintregs[GET_HIGH_REG(s1)], REG_SP, LA_SIZE + 4 * 4 + j * 4);
- j++;
- M_IST(rd->argintregs[GET_LOW_REG(s1)], REG_SP, LA_SIZE + 4 * 4 + j * 4);
- } else {
- M_IST(rd->argintregs[s1], REG_SP, LA_SIZE + 4 * 4 + j * 4);
- }
- j++;
- }
- }
- }
+ disp = cd->stackframesize * 4 - sizeof(stackframeinfo) +
+ OFFSET(stackframeinfo, intregs);
+
+ for (i = 0; i < INT_SAV_CNT; i++)
+ M_AST(abi_registers_integer_saved[i], REG_SP, disp + i * 4);
+#endif
+
+ /* save integer and float argument registers */
for (i = 0; i < md->paramcount; i++) {
- if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
- if (!md->params[i].inmemory) {
- s1 = md->params[i].regoff;
- M_DST(rd->argfltregs[s1], REG_SP, LA_SIZE + 4 * 4 + j * 8);
- j++;
+ if (!md->params[i].inmemory) {
+ s1 = md->params[i].regoff;
+
+ switch (md->paramtypes[i].type) {
+ case TYPE_INT:
+ case TYPE_ADR:
+ M_IST(s1, REG_SP, LA_SIZE + 4*4 + i * 8);
+ break;
+ case TYPE_LNG:
+ M_LST(s1, REG_SP, LA_SIZE + 4*4 + i * 8);
+ break;
+ case TYPE_FLT:
+ case TYPE_DBL:
+ M_DST(s1, REG_SP, LA_SIZE + 4*4 + i * 8);
+ break;
}
}
}
/* create native stack info */
- M_AADD_IMM(REG_SP, cd->stackframesize * 4, REG_A0);
+ M_AADD_IMM(REG_SP, cd->stackframesize * 8, REG_A0);
M_MOV(REG_PV, REG_A1);
- M_AADD_IMM(REG_SP, cd->stackframesize * 4, REG_A2);
- M_ALD(REG_A3, REG_SP, cd->stackframesize * 4 + LA_LR_OFFSET);
+ M_AADD_IMM(REG_SP, cd->stackframesize * 8, REG_A2);
+ M_ALD(REG_A3, REG_SP, cd->stackframesize * 8 + LA_LR_OFFSET);
disp = dseg_add_functionptr(cd, codegen_start_native_call);
M_ALD(REG_ITMP1, REG_PV, disp);
M_MTCTR(REG_ITMP1);
/* restore integer and float argument registers */
- j = 0;
-
for (i = 0; i < md->paramcount; i++) {
- t = md->paramtypes[i].type;
+ if (!md->params[i].inmemory) {
+ s1 = md->params[i].regoff;
- if (IS_INT_LNG_TYPE(t)) {
- if (!md->params[i].inmemory) {
- s1 = md->params[i].regoff;
-
- if (IS_2_WORD_TYPE(t)) {
- M_ILD(rd->argintregs[GET_HIGH_REG(s1)], REG_SP, LA_SIZE + 4 * 4 + j * 4);
- j++;
- M_ILD(rd->argintregs[GET_LOW_REG(s1)], REG_SP, LA_SIZE + 4 * 4 + j * 4);
- } else {
- M_ILD(rd->argintregs[s1], REG_SP, LA_SIZE + 4 * 4 + j * 4);
- }
- j++;
+ switch (md->paramtypes[i].type) {
+ case TYPE_INT:
+ case TYPE_ADR:
+ M_ILD(s1, REG_SP, LA_SIZE + 4*4 + i * 8);
+ break;
+ case TYPE_LNG:
+ M_LLD(s1, REG_SP, LA_SIZE + 4*4 + i * 8);
+ break;
+ case TYPE_FLT:
+ case TYPE_DBL:
+ M_DLD(s1, REG_SP, LA_SIZE + 4*4 + i * 8);
+ break;
}
}
}
- for (i = 0; i < md->paramcount; i++) {
- if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
- if (!md->params[i].inmemory) {
- s1 = md->params[i].regoff;
- M_DLD(rd->argfltregs[s1], REG_SP, LA_SIZE + 4 * 4 + j * 8);
- j++;
- }
- }
- }
-
/* copy or spill arguments to new locations */
for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
if (IS_INT_LNG_TYPE(t)) {
if (!md->params[i].inmemory) {
- if (IS_2_WORD_TYPE(t))
- s1 = PACK_REGS(
- rd->argintregs[GET_LOW_REG(md->params[i].regoff)],
- rd->argintregs[GET_HIGH_REG(md->params[i].regoff)]);
- else
- s1 = rd->argintregs[md->params[i].regoff];
+ s1 = md->params[i].regoff;
+ s2 = nmd->params[j].regoff;
if (!nmd->params[j].inmemory) {
- if (IS_2_WORD_TYPE(t)) {
- s2 = PACK_REGS(
- rd->argintregs[GET_LOW_REG(nmd->params[j].regoff)],
- rd->argintregs[GET_HIGH_REG(nmd->params[j].regoff)]);
+ if (IS_2_WORD_TYPE(t))
M_LNGMOVE(s1, s2);
- } else {
- s2 = rd->argintregs[nmd->params[j].regoff];
+ else
M_INTMOVE(s1, s2);
- }
-
- } else {
- s2 = nmd->params[j].regoff;
+ }
+ else {
if (IS_2_WORD_TYPE(t))
- M_LST(s1, REG_SP, s2 * 4);
+ M_LST(s1, REG_SP, s2);
else
- M_IST(s1, REG_SP, s2 * 4);
+ M_IST(s1, REG_SP, s2);
}
-
- } else {
- s1 = md->params[i].regoff + cd->stackframesize;
+ }
+ else {
+ s1 = md->params[i].regoff + cd->stackframesize * 8;
s2 = nmd->params[j].regoff;
- M_ILD(REG_ITMP1, REG_SP, s1 * 4);
+ M_ILD(REG_ITMP1, REG_SP, s1);
if (IS_2_WORD_TYPE(t))
- M_ILD(REG_ITMP2, REG_SP, s1 * 4 + 4);
+ M_ILD(REG_ITMP2, REG_SP, s1 + 4);
- M_IST(REG_ITMP1, REG_SP, s2 * 4);
+ M_IST(REG_ITMP1, REG_SP, s2);
if (IS_2_WORD_TYPE(t))
- M_IST(REG_ITMP2, REG_SP, s2 * 4 + 4);
+ M_IST(REG_ITMP2, REG_SP, s2 + 4);
}
-
- } else {
+ }
+ else {
/* We only copy spilled float arguments, as the float
argument registers keep unchanged. */
if (md->params[i].inmemory) {
- s1 = md->params[i].regoff + cd->stackframesize;
+ s1 = md->params[i].regoff + cd->stackframesize * 8;
s2 = nmd->params[j].regoff;
- if (IS_2_WORD_TYPE(t)) {
- M_DLD(REG_FTMP1, REG_SP, s1 * 4);
- M_DST(REG_FTMP1, REG_SP, s2 * 4);
+ M_DLD(REG_FTMP1, REG_SP, s1);
- } else {
- M_FLD(REG_FTMP1, REG_SP, s1 * 4);
- M_FST(REG_FTMP1, REG_SP, s2 * 4);
- }
+ if (IS_2_WORD_TYPE(t))
+ M_DST(REG_FTMP1, REG_SP, s2);
+ else
+ M_FST(REG_FTMP1, REG_SP, s2);
}
}
}
/* print call trace */
- if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
- emit_verbosecall_exit(jd);
+ emit_verbosecall_exit(jd);
/* save return value */
- if (md->returntype.type != TYPE_VOID) {
- if (IS_INT_LNG_TYPE(md->returntype.type)) {
- if (IS_2_WORD_TYPE(md->returntype.type))
- M_IST(REG_RESULT2, REG_SP, LA_SIZE + 2 * 4);
- M_IST(REG_RESULT, REG_SP, LA_SIZE + 1 * 4);
- }
- else {
- if (IS_2_WORD_TYPE(md->returntype.type))
- M_DST(REG_FRESULT, REG_SP, LA_SIZE + 1 * 4);
- else
- M_FST(REG_FRESULT, REG_SP, LA_SIZE + 1 * 4);
- }
+ switch (md->returntype.type) {
+ case TYPE_INT:
+ case TYPE_ADR:
+ M_IST(REG_RESULT, REG_SP, LA_SIZE + 1 * 8);
+ break;
+ case TYPE_LNG:
+ M_LST(REG_RESULT_PACKED, REG_SP, LA_SIZE + 1 * 8);
+ break;
+ case TYPE_FLT:
+ case TYPE_DBL:
+ M_DST(REG_FRESULT, REG_SP, LA_SIZE + 1 * 8);
+ break;
+ case TYPE_VOID:
+ break;
}
/* remove native stackframe info */
- M_AADD_IMM(REG_SP, cd->stackframesize * 4, REG_A0);
+ M_AADD_IMM(REG_SP, cd->stackframesize * 8, REG_A0);
disp = dseg_add_functionptr(cd, codegen_finish_native_call);
M_ALD(REG_ITMP1, REG_PV, disp);
M_MTCTR(REG_ITMP1);
/* restore return value */
- if (md->returntype.type != TYPE_VOID) {
- if (IS_INT_LNG_TYPE(md->returntype.type)) {
- if (IS_2_WORD_TYPE(md->returntype.type))
- M_ILD(REG_RESULT2, REG_SP, LA_SIZE + 2 * 4);
- M_ILD(REG_RESULT, REG_SP, LA_SIZE + 1 * 4);
- }
- else {
- if (IS_2_WORD_TYPE(md->returntype.type))
- M_DLD(REG_FRESULT, REG_SP, LA_SIZE + 1 * 4);
- else
- M_FLD(REG_FRESULT, REG_SP, LA_SIZE + 1 * 4);
- }
+ switch (md->returntype.type) {
+ case TYPE_INT:
+ case TYPE_ADR:
+ M_ILD(REG_RESULT, REG_SP, LA_SIZE + 1 * 8);
+ break;
+ case TYPE_LNG:
+ M_LLD(REG_RESULT_PACKED, REG_SP, LA_SIZE + 1 * 8);
+ break;
+ case TYPE_FLT:
+ case TYPE_DBL:
+ M_DLD(REG_FRESULT, REG_SP, LA_SIZE + 1 * 8);
+ break;
+ case TYPE_VOID:
+ break;
}
- M_ALD(REG_ITMP2_XPC, REG_SP, cd->stackframesize * 4 + LA_LR_OFFSET);
+#if defined(ENABLE_GC_CACAO)
+ /* Restore callee saved integer registers from stackframeinfo (GC
+ might have modified them during a collection). */
+
+ disp = cd->stackframesize * 4 - sizeof(stackframeinfo) +
+ OFFSET(stackframeinfo, intregs);
+
+ for (i = 0; i < INT_SAV_CNT; i++)
+ M_ALD(abi_registers_integer_saved[i], REG_SP, disp + i * 4);
+#endif
+
+ M_ALD(REG_ITMP2_XPC, REG_SP, cd->stackframesize * 8 + LA_LR_OFFSET);
M_MTLR(REG_ITMP2_XPC);
- M_LDA(REG_SP, REG_SP, cd->stackframesize * 4); /* remove stackframe */
+ M_LDA(REG_SP, REG_SP, cd->stackframesize * 8); /* remove stackframe */
/* check for exception */
M_MTCTR(REG_ITMP3);
M_RTS;
- /* generate patcher stubs */
-
- emit_patcher_stubs(jd);
-
- codegen_finish(jd);
+ /* generate patcher traps */
- return code->entrypoint;
+ emit_patcher_traps(jd);
}