-/* src/vm/jit/x86_64/codegen.c - machine code generator for x86_64
+/* src/vm/jit/s390/codegen.c - machine code generator for s390
- 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
- Christian Thalinger
- Christian Ullrich
- Edwin Steiner
-
- $Id: codegen.c 7312 2007-02-10 00:49:37Z pm $
-
*/
#include "config.h"
#include <assert.h>
+#include <stdint.h>
#include <stdio.h>
-#include "vm/types.h"
-
-#include "md-abi.h"
-
-#include "vm/jit/s390/arch.h"
-#include "vm/jit/s390/codegen.h"
-#include "vm/jit/s390/emit.h"
-
-#include "mm/memory.h"
#include "native/jni.h"
+#include "native/localref.h"
#include "native/native.h"
+#include "mm/memory.h"
+
#if defined(ENABLE_THREADS)
+# include "threads/lock-common.h"
# include "threads/native/lock.h"
#endif
+#include "vmcore/loader.h"
+#include "vmcore/options.h"
+#include "vmcore/statistics.h"
#include "vm/builtin.h"
#include "vm/exceptions.h"
#include "vm/global.h"
-#include "vm/loader.h"
-#include "vm/options.h"
-#include "vm/statistics.h"
-#include "vm/stringlocal.h"
-#include "vm/vm.h"
+#include "vm/jit/abi.h"
+#if defined(ENABLE_LSRA)
+# include "vm/jit/allocator/lsra.h"
+#endif
#include "vm/jit/asmpart.h"
#include "vm/jit/codegen-common.h"
#include "vm/jit/dseg.h"
#include "vm/jit/jit.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/s390/arch.h"
+#include "vm/jit/s390/codegen.h"
+#include "vm/jit/s390/emit.h"
+#include "vm/jit/s390/md-abi.h"
+#include "vm/jit/stacktrace.h"
+#include "vm/types.h"
+#include "vm/stringlocal.h"
+#include "vm/vm.h"
-#if defined(ENABLE_LSRA)
-# include "vm/jit/allocator/lsra.h"
-#endif
-
-#define OOPS() assert(0);
-
-#if 0
-u1 *createcompilerstub(methodinfo *m) {
- OOPS();
- u1 *stub = malloc(8);
- bzero(stub, 8);
- return stub;
-}
-#endif
+/* DO__LOG generates a call to do__log. No registers are destroyed,
+ * so you may use it anywhere. regs is an array containing all general
+ * purpose registers.
+ */
-#if 0
-u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd) {
- OOPS();
- return createcompilerstub(NULL);
+static void do__log(u4 *regs) {
+ /* insert stuff here */
}
-#endif
+#define DO__LOG \
+ N_AHI(REG_SP, -200); \
+ N_STM(R0, R15, 96, REG_SP); \
+ M_ALD_DSEG(R14, dseg_add_address(cd, &do__log)); \
+ N_LA(R2, 96, RN, REG_SP); \
+ N_BASR(R14, R14); \
+ N_LM(R0, R15, 96, REG_SP); \
+ N_AHI(REG_SP, 200);
+#define SUPPORT_HERCULES 1
/* codegen *********************************************************************
*******************************************************************************/
+/*
+
+Layout of stackframe:
+
+Meaning Offset
+===============================================================================
+return_address (stackframesize - 1) * 8
+saved_int_reg[INT_SAV_CNT - 1] (stackframseize - 2) * 8
+...
+saved_int_reg[rd->savintreguse]
+saved_flt_reg[FLT_SAV_CNT - 1]
+...
+saved_flt_reg[rd->savfltreguse] (stackframesize - 1 - savedregs_num) * 8
+
+return_value_tmp (rd->memuse + 1) * 8
+monitorenter_argument (rd->memuse) * 8
+???
+local[rd->memuse - 1] (rd->memuse - 1) * 8
+....
+local[2] 2 * 8
+local[1] 1 * 8
+local[0] 0 * 8
+
+*/
-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 len, s1, s2, s3, d, dd, disp;
u2 currentline;
ptrint a;
varinfo *var, *var1, *var2, *dst;
s4 i, p, t, l;
s4 savedregs_num;
- savedregs_num = 1; /* space to save RA */
+ savedregs_num = 0;
/* 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;
+ cd->stackframesize = rd->memuse + savedregs_num + 1 /* space to save RA */;
/* CAUTION:
* As REG_ITMP3 == REG_RA, do not touch REG_ITMP3, until it has been saved.
*/
#if defined(ENABLE_THREADS)
- /* space to save argument of monitor_enter */
- OOPS(); /* see powerpc */
-#if 0
- if (checksync && (m->flags & ACC_SYNCHRONIZED))
- cd->stackframesize++;
-#endif
+ /* Space to save argument of monitor_enter and Return Values to
+ survive monitor_exit. The stack position for the argument can
+ not be shared with place to save the return register
+ since both values reside in R2. */
+
+ if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
+ /* 1 slot space to save argument of monitor_enter */
+ /* 1 slot to temporary store return value before monitor_exit */
+ cd->stackframesize += 2;
+ }
#endif
/* Keep stack of non-leaf functions 16-byte aligned for calls into
native code e.g. libc or jni (alignment problems with
movaps). */
- if (!jd->isleafmethod || opt_verbosecall)
+ if (!jd->isleafmethod || opt_verbosecall )
/* TODO really 16 bytes ? */
- cd->stackframesize = (cd->stackframesize + 3) & ~3;
+ cd->stackframesize = (cd->stackframesize + 2) & ~2;
/* 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 */
#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 */
-
+ (void) dseg_add_unique_s4(cd, 0); /* IsSync */
+
(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_add_target(cd, ex->handler);
(void) dseg_add_unique_address(cd, ex->catchtype.any);
}
-
+
+ /* Offset PV */
+
+ M_AADD_IMM(N_PV_OFFSET, REG_PV);
+
/* generate method profiling code */
+#if defined(ENABLE_PROFILING)
if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
/* count frequency */
-
- M_ALD(REG_ITMP1, REG_PV, CodeinfoPointer);
- M_ILD(REG_ITMP2, REG_ITMP1, OFFSET(codeinfo, frequency));
- M_IADD_IMM(1, REG_ITMP2);
+ M_ALD_DSEG(REG_ITMP1, CodeinfoPointer);
+ ICONST(REG_ITMP2, 1);
+ N_AL(REG_ITMP2, OFFSET(codeinfo, frequency), RN, REG_ITMP1);
M_IST(REG_ITMP2, REG_ITMP1, OFFSET(codeinfo, frequency));
-/* PROFILE_CYCLE_START; */
+ PROFILE_CYCLE_START;
}
+#endif
/* create stack frame (if necessary) */
if (cd->stackframesize)
- M_ASUB_IMM(cd->stackframesize * 4, REG_SP);
+ M_ASUB_IMM(cd->stackframesize * 8, REG_SP);
/* save used callee saved registers and return address */
p = cd->stackframesize;
- p--; M_AST(REG_RA, REG_SP, p * 4);
+ p--; M_AST(REG_RA, REG_SP, p * 8);
+
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 */
varindex = jd->local_map[l * 5 + t];
l++;
- if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
- l++;
+
+ if (IS_2_WORD_TYPE(t))
+ l++;
if (varindex == UNUSED)
continue;
var = VAR(varindex);
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 (IS_2_WORD_TYPE(t)) {
+ s2 = PACK_REGS(
+ GET_LOW_REG(s1),
+ GET_HIGH_REG(s1)
+ );
+ } else {
+ s2 = s1;
+ }
if (!md->params[p].inmemory) { /* register arguments */
if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
- if (IS_2_WORD_TYPE(t))
+ if (IS_2_WORD_TYPE(t)) {
M_LNGMOVE(s2, var->vv.regoff);
- else
+ } else {
M_INTMOVE(s2, var->vv.regoff);
-
+ }
} else { /* reg arg -> spilled */
- if (IS_2_WORD_TYPE(t))
- M_LST(s2, REG_SP, var->vv.regoff * 4);
- else
- M_IST(s2, REG_SP, var->vv.regoff * 4);
+ if (IS_2_WORD_TYPE(t)) {
+ M_LST(s2, REG_SP, var->vv.regoff);
+ } else {
+ M_IST(s2, REG_SP, var->vv.regoff);
+ }
}
} else { /* stack arguments */
if (!IS_INMEMORY(var->flags)) { /* stack arg -> register */
- if (IS_2_WORD_TYPE(t))
- M_LLD(var->vv.regoff, REG_SP, (cd->stackframesize + s1) * 4);
- else
- M_ILD(var->vv.regoff, REG_SP, (cd->stackframesize + s1) * 4);
-
- } else { /* stack arg -> spilled */
- M_ILD(REG_ITMP1, REG_SP, (cd->stackframesize + s1) * 4);
- M_IST(REG_ITMP1, REG_SP, var->vv.regoff * 4);
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_LLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
+ } else {
+ M_ILD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
}
+ } else { /* stack arg -> spilled */
+ N_MVC(var->vv.regoff, 8, REG_SP, cd->stackframesize * 8 + s1, REG_SP);
}
}
} else { /* floating args */
if (!md->params[p].inmemory) { /* register arguments */
- s2 = rd->argfltregs[s1];
+ s2 = 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);
+ M_DST(s2, REG_SP, var->vv.regoff);
else
- M_FST(s2, REG_SP, var->vv.regoff * 4);
+ M_FST(s2, REG_SP, var->vv.regoff);
}
} 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);
+ M_DLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
else
- M_FLD(var->vv.regoff, REG_SP, (cd->stackframesize + s1) * 4);
+ M_FLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
} else { /* stack-arg -> spilled */
- 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);
- }
+ N_MVC(var->vv.regoff, 8, REG_SP, cd->stackframesize * 8 + s1, REG_SP);
+ var->vv.regoff = cd->stackframesize * 8 + s1;
}
}
}
s1 = rd->memuse;
+#if !defined(NDEBUG)
if (opt_verbosecall) {
- M_LSUB_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
+ M_ASUB_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
for (p = 0; p < INT_ARG_CNT; p++)
- M_LST(rd->argintregs[p], REG_SP, p * 8);
+ M_IST(abi_registers_integer_argument[p], REG_SP, p * 8);
for (p = 0; p < FLT_ARG_CNT; p++)
- M_DST(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 8);
+ M_DST(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
- s1 += INT_ARG_CNT + FLT_ARG_CNT;
+ s1 += ((INT_ARG_CNT + FLT_ARG_CNT));
}
+#endif
/* decide which monitor enter function to call */
if (m->flags & ACC_STATIC) {
- M_MOV_IMM(&m->class->object.header, REG_A0);
+ disp = dseg_add_address(cd, &m->class->object.header);
+ M_ALD_DSEG(REG_A0, disp);
}
else {
M_TEST(REG_A0);
- M_BEQ(0);
- codegen_add_nullpointerexception_ref(cd);
+ M_BNE(SZ_BRC + SZ_ILL);
+ M_ILL(EXCEPTION_HARDWARE_NULLPOINTER);
}
+ disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
+ M_ALD_DSEG(REG_ITMP3, disp);
+
M_AST(REG_A0, REG_SP, s1 * 8);
- M_MOV_IMM(LOCK_monitor_enter, REG_ITMP1);
- M_CALL(REG_ITMP1);
+ M_ASUB_IMM(96, REG_SP);
+ M_CALL(REG_ITMP3);
+ M_AADD_IMM(96, REG_SP);
+
+#if !defined(NDEBUG)
if (opt_verbosecall) {
for (p = 0; p < INT_ARG_CNT; p++)
- M_LLD(rd->argintregs[p], REG_SP, p * 8);
+ M_ILD(abi_registers_integer_argument[p], REG_SP, p * 8);
for (p = 0; p < FLT_ARG_CNT; p++)
- M_DLD(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 8);
+ M_DLD(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
- M_LADD_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
+ M_AADD_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
}
+#endif
}
#endif
}
/* end of header generation */
-#if 0
- replacementpoint = jd->code->rplpoints;
-#endif
+
+ /* create replacement points */
+
+ REPLACEMENT_POINTS_INIT(cd, jd);
/* walk through all basic blocks */
/* handle replacement points */
-#if 0
- if (bptr->bitflags & BBFLAG_REPLACEMENT) {
- replacementpoint->pc = (u1*)(ptrint)bptr->mpc; /* will be resolved later */
-
- replacementpoint++;
-
- assert(cd->lastmcodeptr <= cd->mcodeptr);
- cd->lastmcodeptr = cd->mcodeptr + 5; /* 5 byte jmp patch */
- }
-#endif
+ REPLACEMENT_POINT_BLOCK_START(cd, bptr);
/* copy interface registers to their destination */
len = bptr->indepth;
MCODECHECK(512);
+#if defined(ENABLE_PROFILING)
/* generate basicblock profiling code */
if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
/* count frequency */
- M_MOV_IMM(code->bbfrequency, REG_ITMP3);
- M_IINC_MEMBASE(REG_ITMP3, bptr->nr * 4);
+ M_ALD_DSEG(REG_ITMP1, CodeinfoPointer);
+ M_ALD(REG_ITMP1, REG_ITMP1, OFFSET(codeinfo, bbfrequency));
+ ICONST(REG_ITMP2, 1);
+ N_AL(REG_ITMP2, bptr->nr * 4, RN, REG_ITMP1);
+ M_IST(REG_ITMP2, REG_ITMP1, bptr->nr * 4);
/* if this is an exception handler, start profiling again */
if (bptr->type == BBTYPE_EXH)
PROFILE_CYCLE_START;
}
+#endif
#if defined(ENABLE_LSRA)
if (opt_lsra) {
case ICMD_NOP: /* ... ==> ... */
case ICMD_POP: /* ..., value ==> ... */
case ICMD_POP2: /* ..., value, value ==> ... */
- case ICMD_INLINE_START: /* internal ICMDs */
+ break;
+
+ case ICMD_INLINE_START:
+
+ REPLACEMENT_POINT_INLINE_START(cd, iptr);
+ break;
+
+ case ICMD_INLINE_BODY:
+
+ REPLACEMENT_POINT_INLINE_BODY(cd, iptr);
+ dseg_addlinenumber_inline_start(cd, iptr);
+ dseg_addlinenumber(cd, iptr->line);
+ break;
+
case ICMD_INLINE_END:
+
+ dseg_addlinenumber_inline_end(cd, iptr);
+ dseg_addlinenumber(cd, iptr->line);
break;
case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
- OOPS();
-#if 0
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- M_TEST(s1);
- M_BEQ(0);
- codegen_add_nullpointerexception_ref(cd);
-#endif
+ emit_nullpointer_check(cd, iptr, s1);
break;
/* constant operations ************************************************/
break;
case ICMD_LCONST: /* ... ==> ..., constant */
- OOPS();
-#if 0
- d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+
+ d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
LCONST(d, iptr->sx.val.l);
emit_store_dst(jd, iptr, d);
-#endif
break;
case ICMD_FCONST: /* ... ==> ..., constant */
d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
disp = dseg_add_float(cd, iptr->sx.val.f);
- M_FLDN(d, REG_PV, disp, REG_ITMP1);
+ M_FLD_DSEG(d, disp, REG_ITMP1);
emit_store_dst(jd, iptr, d);
break;
case ICMD_DCONST: /* ... ==> ..., constant */
- OOPS();
-#if 0
d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
disp = dseg_add_double(cd, iptr->sx.val.d);
- emit_movd_membase_reg(cd, RIP, -((cd->mcodeptr + 9) - cd->mcodebase) + disp, d);
+ M_DLD_DSEG(d, disp, REG_ITMP1);
emit_store_dst(jd, iptr, d);
-#endif
break;
case ICMD_ACONST: /* ... ==> ..., constant */
/* PROFILE_CYCLE_STOP; */
- codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_classinfo,
+ patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
cr, disp);
/* PROFILE_CYCLE_START; */
- M_ALD(d, REG_PV, disp);
+ M_ALD_DSEG(d, disp);
} else {
if (iptr->sx.val.anyptr == 0) {
M_CLR(d);
} else {
disp = dseg_add_unique_address(cd, iptr->sx.val.anyptr);
- M_ALD(d, REG_PV, disp);
+ M_ALD_DSEG(d, disp);
+ /*
+ if (((u4)(iptr->sx.val.anyptr) & 0x00008000) == 0) {
+ N_LHI(d, ((u4)(iptr->sx.val.anyptr) >> 16) & 0xFFFF);
+ M_SLL_IMM(16, d);
+ N_AHI(d, (u4)(iptr->sx.val.anyptr) & 0xFFFF);
+ } else {
+ disp = dseg_add_unique_address(cd, iptr->sx.val.anyptr);
+ M_ALD_DSEG(d, disp);
+ }
+ */
}
}
emit_store_dst(jd, iptr, d);
case ICMD_DSTORE:
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;
/* integer operations *************************************************/
case ICMD_INEG: /* ..., value ==> ..., - value */
- OOPS();
-#if 0
+
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
- M_INTMOVE(s1, d);
- M_INEG(d);
+ d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+ M_INEG(s1, d);
emit_store_dst(jd, iptr, d);
-#endif
+
break;
case ICMD_LNEG: /* ..., value ==> ..., - value */
- OOPS();
-#if 0
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
- M_INTMOVE(s1, d);
- M_LNEG(d);
+
+ s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
+ d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
+ M_INEG(GET_HIGH_REG(s1), GET_HIGH_REG(d));
+ M_INEG(GET_LOW_REG(s1), GET_LOW_REG(d));
+ N_BRC(8 /* result zero, no overflow */, SZ_BRC + SZ_AHI);
+ N_AHI(GET_HIGH_REG(d), -1);
emit_store_dst(jd, iptr, d);
-#endif
break;
case ICMD_I2L: /* ..., value ==> ..., value */
- OOPS();
-#if 0
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
- M_ISEXT(s1, d);
+
+ d = emit_alloc_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
+ s1 = emit_load_s1(jd, iptr, GET_HIGH_REG(d));
+
+ M_INTMOVE(s1, GET_HIGH_REG(d));
+ ICONST(GET_LOW_REG(d), 0);
+ M_SRDA_IMM(32, GET_HIGH_REG(d));
+
+ emit_copy_dst(jd, iptr, d);
emit_store_dst(jd, iptr, d);
-#endif
+ emit_restore_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
+
break;
case ICMD_L2I: /* ..., value ==> ..., value */
- OOPS();
-#if 0
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+ s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
- M_IMOV(s1, d);
+ M_INTMOVE(GET_LOW_REG(s1), d);
emit_store_dst(jd, iptr, d);
-#endif
break;
case ICMD_INT2BYTE: /* ..., value ==> ..., value */
- OOPS();
-#if 0
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
- M_BSEXT(s1, d);
+ M_INTMOVE(s1, d);
+ M_SLL_IMM(24, d);
+ M_SRA_IMM(24, d);
emit_store_dst(jd, iptr, d);
-#endif
break;
case ICMD_INT2CHAR: /* ..., value ==> ..., value */
- OOPS();
-#if 0
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
- M_CZEXT(s1, d);
+ M_INTMOVE(s1, d);
+ M_SLL_IMM(16, d);
+ M_SRL_IMM(16, d);
emit_store_dst(jd, iptr, d);
-#endif
break;
case ICMD_INT2SHORT: /* ..., value ==> ..., value */
- OOPS();
-#if 0
+
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
- M_SSEXT(s1, d);
+ M_INTMOVE(s1, d);
+ M_SLL_IMM(16, d);
+ M_SRA_IMM(16, d);
emit_store_dst(jd, iptr, d);
-#endif
break;
-
case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
- OOPS();
-#if 0
+
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
M_IADD(s2, d);
}
emit_store_dst(jd, iptr, d);
-#endif
+
break;
case ICMD_IINC:
/* sx.val.i = constant */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
-
M_INTMOVE(s1, d);
- M_IADD_IMM(iptr->sx.val.i, d);
+
+ if (N_VALID_IMM(iptr->sx.val.i)) {
+ M_IADD_IMM(iptr->sx.val.i, d);
+ } else {
+ ICONST(REG_ITMP2, iptr->sx.val.i);
+ M_IADD(REG_ITMP2, d);
+ }
emit_store_dst(jd, iptr, d);
break;
case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
- OOPS();
-#if 0
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
- if (s2 == d)
- M_LADD(s1, d);
- else {
- M_INTMOVE(s1, d);
- M_LADD(s2, d);
+
+ /* M, (r, q) -> (r, q) */
+
+ d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
+
+ s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
+ s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
+ dd = GET_HIGH_REG(d);
+
+ if (s2 == dd) {
+ M_IADD(s1, dd);
+ } else {
+ M_INTMOVE(s1, dd);
+ M_IADD(s2, dd);
+ }
+
+ s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
+ s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
+ dd = GET_LOW_REG(d);
+
+ if (s2 == dd) {
+ N_ALR(dd, s1);
+ } else {
+ M_INTMOVE(s1, dd);
+ N_ALR(dd, s2);
}
+
+ N_BRC(8 | 4, SZ_BRC + SZ_AHI);
+ N_AHI(GET_HIGH_REG(d), 1);
+
emit_store_dst(jd, iptr, d);
-#endif
break;
case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
/* sx.val.l = constant */
- OOPS();
-#if 0
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
- M_INTMOVE(s1, d);
- if (IS_IMM32(iptr->sx.val.l))
- M_LADD_IMM(iptr->sx.val.l, d);
- else {
- M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
- M_LADD(REG_ITMP2, d);
+
+ d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
+ dd = GET_HIGH_REG(d);
+
+ s1 = emit_load_s1_high(jd, iptr, dd);
+ s3 = iptr->sx.val.l >> 32;
+
+ M_INTMOVE(s1, dd);
+
+ if (N_VALID_IMM(s3)) {
+ M_IADD_IMM(s3, dd);
+ } else {
+ ICONST(REG_ITMP3, s3);
+ M_IADD(REG_ITMP3, dd);
}
+
+ dd = GET_LOW_REG(d);
+ s1 = emit_load_s1_low(jd, iptr, dd);
+ s3 = iptr->sx.val.l & 0xffffffff;
+ ICONST(REG_ITMP3, s3);
+
+ M_INTMOVE(s1, dd);
+ N_ALR(dd, REG_ITMP3);
+
+ N_BRC(8 | 4, SZ_BRC + SZ_AHI);
+ N_AHI(GET_HIGH_REG(d), 1);
+
emit_store_dst(jd, iptr, d);
-#endif
break;
case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
- OOPS();
-#if 0
+
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
M_ISUB(s2, d);
}
emit_store_dst(jd, iptr, d);
-#endif
+
break;
case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
/* sx.val.i = constant */
- OOPS();
-#if 0
+
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
M_INTMOVE(s1, d);
- M_ISUB_IMM(iptr->sx.val.i, d);
+
+ if (N_VALID_IMM(-iptr->sx.val.i)) {
+ M_ISUB_IMM(iptr->sx.val.i, d);
+ } else {
+ ICONST(REG_ITMP2, iptr->sx.val.i);
+ M_ISUB(REG_ITMP2, d);
+ }
emit_store_dst(jd, iptr, d);
-#endif
+
break;
case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
- OOPS();
-#if 0
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
- if (s2 == d) {
- M_INTMOVE(s1, REG_ITMP1);
- M_LSUB(s2, REG_ITMP1);
- M_INTMOVE(REG_ITMP1, d);
- } else {
- M_INTMOVE(s1, d);
- M_LSUB(s2, d);
+
+ d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
+
+ s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
+ s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
+ dd = GET_HIGH_REG(d);
+
+ if (s2 == dd) {
+ M_INTMOVE(s2, REG_ITMP3);
+ s2 = REG_ITMP3;
}
+
+ M_INTMOVE(s1, dd);
+ M_ISUB(s2, dd);
+
+ s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
+ s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
+ dd = GET_LOW_REG(d);
+
+ if (s2 == dd) {
+ M_INTMOVE(s2, REG_ITMP3);
+ s2 = REG_ITMP3;
+ }
+
+ M_INTMOVE(s1, dd);
+ N_SLR(dd, s2);
+
+ N_BRC(1 | 2, SZ_BRC + SZ_AHI);
+ N_AHI(GET_HIGH_REG(d), -1);
+
emit_store_dst(jd, iptr, d);
-#endif
break;
case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
/* sx.val.l = constant */
- OOPS();
-#if 0
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
- M_INTMOVE(s1, d);
- if (IS_IMM32(iptr->sx.val.l))
- M_LSUB_IMM(iptr->sx.val.l, d);
- else {
- M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
- M_LSUB(REG_ITMP2, d);
+
+ d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
+
+ dd = GET_HIGH_REG(d);
+ s1 = emit_load_s1_high(jd, iptr, dd);
+ s3 = iptr->sx.val.l >> 32;
+
+ M_INTMOVE(s1, dd);
+
+ if (N_VALID_IMM(-s3)) {
+ M_IADD_IMM(-s3, dd);
+ } else {
+ ICONST(REG_ITMP3, s3);
+ M_ISUB(REG_ITMP3, dd);
}
+
+ dd = GET_LOW_REG(d);
+ s1 = emit_load_s1_low(jd, iptr, dd);
+ s3 = iptr->sx.val.l & 0xffffffff;
+ ICONST(REG_ITMP3, s3);
+
+ M_INTMOVE(s1, dd);
+ N_SLR(dd, REG_ITMP3);
+
+ N_BRC(1 | 2, SZ_BRC + SZ_AHI);
+ N_AHI(GET_HIGH_REG(d), -1);
+
emit_store_dst(jd, iptr, d);
-#endif
break;
case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
- OOPS();
-#if 0
+
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
M_IMUL(s2, d);
}
emit_store_dst(jd, iptr, d);
-#endif
+
break;
case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
/* sx.val.i = constant */
- OOPS();
-#if 0
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+ M_INTMOVE(s1, d);
if (iptr->sx.val.i == 2) {
- M_INTMOVE(s1, d);
- M_ISLL_IMM(1, d);
- } else
- M_IMUL_IMM(s1, iptr->sx.val.i, d);
+ M_SLL_IMM(1, d);
+ } else if (N_VALID_IMM(iptr->sx.val.i)) {
+ M_IMUL_IMM(iptr->sx.val.i, d);
+ } else {
+ disp = dseg_add_s4(cd, iptr->sx.val.i);
+ M_ILD_DSEG(REG_ITMP2, disp);
+ M_IMUL(REG_ITMP2, d);
+ }
emit_store_dst(jd, iptr, d);
-#endif
- break;
-
- case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
- OOPS();
-#if 0
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
- if (s2 == d)
- M_LMUL(s1, d);
- else {
- M_INTMOVE(s1, d);
- M_LMUL(s2, d);
- }
- emit_store_dst(jd, iptr, d);
-#endif
- break;
-
- case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
- /* sx.val.l = constant */
- OOPS();
-#if 0
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
- if (IS_IMM32(iptr->sx.val.l))
- M_LMUL_IMM(s1, iptr->sx.val.l, d);
- else {
- M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
- M_INTMOVE(s1, d);
- M_LMUL(REG_ITMP2, d);
- }
- emit_store_dst(jd, iptr, d);
-#endif
break;
case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
- OOPS();
-#if 0
- var1 = VAROP(iptr->s1);
- var2 = VAROP(iptr->sx.s23.s2);
- dst = VAROP(iptr->dst);
+ case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
- d = codegen_reg_of_dst(jd, iptr, REG_NULL);
- if (IS_INMEMORY(var1->flags))
- M_ILD(RAX, REG_SP, var1->vv.regoff * 8);
- else
- M_INTMOVE(var1->vv.regoff, RAX);
-
- if (IS_INMEMORY(var2->flags))
- M_ILD(REG_ITMP3, REG_SP, var2->vv.regoff * 8);
- else
- M_INTMOVE(var2->vv.regoff, REG_ITMP3);
-
- if (checknull) {
- M_ITEST(REG_ITMP3);
- M_BEQ(0);
- codegen_add_arithmeticexception_ref(cd);
- }
+ s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
+ emit_arithmetic_check(cd, iptr, s2);
- emit_alul_imm_reg(cd, ALU_CMP, 0x80000000, RAX); /* check as described in jvm spec */
- emit_jcc(cd, CC_NE, 4 + 6);
- emit_alul_imm_reg(cd, ALU_CMP, -1, REG_ITMP3); /* 4 bytes */
- emit_jcc(cd, CC_E, 3 + 1 + 3); /* 6 bytes */
+ /* For this operation we need a register pair.
+ * We will use r0 and itmp1 and will backup r0.
+ */
- emit_mov_reg_reg(cd, RDX, REG_ITMP2); /* save %rdx, cause it's an argument register */
- emit_cltd(cd);
- emit_idivl_reg(cd, REG_ITMP3);
+ M_INTMOVE(R0, REG_ITMP3);
- if (IS_INMEMORY(dst->flags)) {
- emit_mov_reg_membase(cd, RAX, REG_SP, dst->vv.regoff * 8);
- emit_mov_reg_reg(cd, REG_ITMP2, RDX); /* restore %rdx */
+ /* We won't check for division by 0, we catch a SIGFPE instead
+ * Special case 0x80000000 / 0xffffffff handled by signal handler too.
+ */
- } else {
- M_INTMOVE(RAX, dst->vv.regoff);
+ s1 = emit_load_s1(jd, iptr, R0);
+ M_INTMOVE(s1, R0);
+ M_CLR(REG_ITMP1);
+ M_SRDA_IMM(32, R0);
- if (dst->vv.regoff != RDX) {
- emit_mov_reg_reg(cd, REG_ITMP2, RDX); /* restore %rdx */
- }
+ N_DR(R0, s2);
+
+ switch (iptr->opc) {
+ case ICMD_IREM:
+ d = codegen_reg_of_dst(jd, iptr, R0);
+ M_INTMOVE(R0, d);
+ break;
+ case ICMD_IDIV:
+ d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+ M_INTMOVE(REG_ITMP1, d);
+ break;
}
-#endif
- break;
- case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
- OOPS();
-#if 0
- var1 = VAROP(iptr->s1);
- var2 = VAROP(iptr->sx.s23.s2);
- dst = VAROP(iptr->dst);
+ emit_store_dst(jd, iptr, d);
- d = codegen_reg_of_dst(jd, iptr, REG_NULL);
- if (IS_INMEMORY(var1->flags))
- M_ILD(RAX, REG_SP, var1->vv.regoff * 8);
- else
- M_INTMOVE(var1->vv.regoff, RAX);
-
- if (IS_INMEMORY(var2->flags))
- M_ILD(REG_ITMP3, REG_SP, var2->vv.regoff * 8);
- else
- M_INTMOVE(var2->vv.regoff, REG_ITMP3);
+ /* If destionation of operation was not register R0,
+ * restore R0.
+ */
- if (checknull) {
- M_ITEST(REG_ITMP3);
- M_BEQ(0);
- codegen_add_arithmeticexception_ref(cd);
+ if (! ((d == R0) && !IS_INMEMORY(VAROP(iptr->dst)->flags))) {
+ M_INTMOVE(REG_ITMP3, R0);
}
- emit_mov_reg_reg(cd, RDX, REG_ITMP2); /* save %rdx, cause it's an argument register */
+ break;
- emit_alul_imm_reg(cd, ALU_CMP, 0x80000000, RAX); /* check as described in jvm spec */
- emit_jcc(cd, CC_NE, 2 + 4 + 6);
+ case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
+ case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
+ bte = iptr->sx.s23.s3.bte;
+ md = bte->md;
- emit_alul_reg_reg(cd, ALU_XOR, RDX, RDX); /* 2 bytes */
- emit_alul_imm_reg(cd, ALU_CMP, -1, REG_ITMP3); /* 4 bytes */
- emit_jcc(cd, CC_E, 1 + 3); /* 6 bytes */
+ /* test s2 for zero */
- emit_cltd(cd);
- emit_idivl_reg(cd, REG_ITMP3);
+ s2 = emit_load_s2(jd, iptr, REG_ITMP12_PACKED);
+ M_INTMOVE(GET_LOW_REG(s2), REG_ITMP3);
+ M_IOR(GET_HIGH_REG(s2), REG_ITMP3);
+ emit_arithmetic_check(cd, iptr, REG_ITMP3);
- if (IS_INMEMORY(dst->flags)) {
- emit_mov_reg_membase(cd, RDX, REG_SP, dst->vv.regoff * 8);
- emit_mov_reg_reg(cd, REG_ITMP2, RDX); /* restore %rdx */
+ /* TODO SIGFPE? */
- } else {
- M_INTMOVE(RDX, dst->vv.regoff);
+ disp = dseg_add_functionptr(cd, bte->fp);
- if (dst->vv.regoff != RDX) {
- emit_mov_reg_reg(cd, REG_ITMP2, RDX); /* restore %rdx */
- }
- }
-#endif
- break;
+ /* load arguments */
- case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
- /* sx.val.i = constant */
- OOPS();
-#if 0
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
- M_INTMOVE(s1, REG_ITMP1);
- emit_alul_imm_reg(cd, ALU_CMP, -1, REG_ITMP1);
- emit_leal_membase_reg(cd, REG_ITMP1, (1 << iptr->sx.val.i) - 1, REG_ITMP2);
- emit_cmovccl_reg_reg(cd, CC_LE, REG_ITMP2, REG_ITMP1);
- emit_shiftl_imm_reg(cd, SHIFT_SAR, iptr->sx.val.i, REG_ITMP1);
- emit_mov_reg_reg(cd, REG_ITMP1, d);
- emit_store_dst(jd, iptr, d);
-#endif
- break;
+ M_LNGMOVE(s2, PACK_REGS(REG_A3, REG_A2));
- case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
- /* sx.val.i = constant */
- OOPS();
-#if 0
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
- M_INTMOVE(s1, REG_ITMP1);
- emit_alul_imm_reg(cd, ALU_CMP, -1, REG_ITMP1);
- emit_leal_membase_reg(cd, REG_ITMP1, iptr->sx.val.i, REG_ITMP2);
- emit_cmovccl_reg_reg(cd, CC_G, REG_ITMP1, REG_ITMP2);
- emit_alul_imm_reg(cd, ALU_AND, -1 - (iptr->sx.val.i), REG_ITMP2);
- emit_alul_reg_reg(cd, ALU_SUB, REG_ITMP2, REG_ITMP1);
- emit_mov_reg_reg(cd, REG_ITMP1, d);
- emit_store_dst(jd, iptr, d);
-#endif
- break;
+ s1 = emit_load_s1(jd, iptr, PACK_REGS(REG_A1, REG_A0));
+ M_LNGMOVE(s1, PACK_REGS(REG_A1, REG_A0));
+ /* call builtin */
- case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
- OOPS();
-#if 0
- var1 = VAROP(iptr->s1);
- var2 = VAROP(iptr->sx.s23.s2);
- dst = VAROP(iptr->dst);
+ M_ASUB_IMM(96, REG_SP);
+ M_ALD_DSEG(REG_ITMP3, disp);
+ M_JSR(REG_RA, REG_ITMP3);
+ M_AADD_IMM(96, REG_SP);
- d = codegen_reg_of_dst(jd, iptr, REG_NULL);
+ /* store result */
- if (IS_INMEMORY(var1->flags))
- M_LLD(RAX, REG_SP, var1->vv.regoff * 8);
- else
- M_INTMOVE(var1->vv.regoff, RAX);
-
- if (IS_INMEMORY(var2->flags))
- M_LLD(REG_ITMP3, REG_SP, var2->vv.regoff * 8);
- else
- M_INTMOVE(var2->vv.regoff, REG_ITMP3);
+ d = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
+ M_LNGMOVE(REG_RESULT_PACKED, d);
+ emit_store_dst(jd, iptr, d);
- if (checknull) {
- M_TEST(REG_ITMP3);
- M_BEQ(0);
- codegen_add_arithmeticexception_ref(cd);
- }
+ break;
- /* check as described in jvm spec */
- disp = dseg_add_s8(cd, 0x8000000000000000LL);
- M_LCMP_MEMBASE(RIP, -((cd->mcodeptr + 7) - cd->mcodebase) + disp, RAX);
- M_BNE(4 + 6);
- M_LCMP_IMM(-1, REG_ITMP3); /* 4 bytes */
- M_BEQ(3 + 2 + 3); /* 6 bytes */
+ case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
+ case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
+ case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
- M_MOV(RDX, REG_ITMP2); /* save %rdx, cause it's an argument register */
- emit_cqto(cd);
- emit_idiv_reg(cd, REG_ITMP3);
+ s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+ d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+ s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- if (IS_INMEMORY(dst->flags)) {
- M_LST(RAX, REG_SP, dst->vv.regoff * 8);
- M_MOV(REG_ITMP2, RDX); /* restore %rdx */
+ /* Use only 5 bits of sencond operand. */
- } else {
- M_INTMOVE(RAX, dst->vv.regoff);
+ M_INTMOVE(s2, REG_ITMP2);
+ s2 = REG_ITMP2;
+ ICONST(REG_ITMP3, 0x1F);
+ M_IAND(REG_ITMP3, s2);
- if (dst->vv.regoff != RDX) {
- M_MOV(REG_ITMP2, RDX); /* restore %rdx */
- }
+ M_INTMOVE(s1, d);
+
+ switch (iptr->opc) {
+ case ICMD_ISHL:
+ M_SLL(s2, d);
+ break;
+ case ICMD_ISHR:
+ M_SRA(s2, d);
+ break;
+ case ICMD_IUSHR:
+ M_SRL(s2, d);
+ break;
+ default:
+ assert(0);
}
-#endif
+ emit_store_dst(jd, iptr, d);
break;
- case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
- OOPS();
-#if 0
- var1 = VAROP(iptr->s1);
- var2 = VAROP(iptr->sx.s23.s2);
- dst = VAROP(iptr->dst);
+ case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
+ /* sx.val.i = constant */
+ {
+ u1 *ref;
- d = codegen_reg_of_dst(jd, iptr, REG_NULL);
-
- if (IS_INMEMORY(var1->flags))
- M_LLD(REG_ITMP1, REG_SP, var1->vv.regoff * 8);
- else
- M_INTMOVE(var1->vv.regoff, REG_ITMP1);
-
- if (IS_INMEMORY(var2->flags))
- M_LLD(REG_ITMP3, REG_SP, var2->vv.regoff * 8);
- else
- M_INTMOVE(var2->vv.regoff, REG_ITMP3);
- /*
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- M_INTMOVE(s1, REG_ITMP1);
- s2 = emit_load_s2(jd, iptr, REG_ITMP3);
- M_INTMOVE(s2, REG_ITMP3);
- */
- if (checknull) {
- M_ITEST(REG_ITMP3);
- M_BEQ(0);
- codegen_add_arithmeticexception_ref(cd);
- }
+ assert(iptr->sx.val.i <= 32);
- M_MOV(RDX, REG_ITMP2); /* save %rdx, cause it's an argument register */
+ s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+ d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
- /* check as described in jvm spec */
- disp = dseg_add_s8(cd, 0x8000000000000000LL);
- M_LCMP_MEMBASE(RIP, -((cd->mcodeptr + 7) - cd->mcodebase) + disp, REG_ITMP1);
- M_BNE(3 + 4 + 6);
+ M_INTMOVE(s1, d);
+ M_TEST(d);
+ ref = cd->mcodeptr;
+ M_BGE(0);
-#if 0
- emit_alul_reg_reg(cd, ALU_XOR, RDX, RDX); /* 2 bytes */
-#endif
- M_LXOR(RDX, RDX); /* 3 bytes */
- M_LCMP_IMM(-1, REG_ITMP3); /* 4 bytes */
- M_BEQ(2 + 3); /* 6 bytes */
+ s3 = (1 << iptr->sx.val.i) - 1;
- emit_cqto(cd);
- emit_idiv_reg(cd, REG_ITMP3);
+ if (N_VALID_IMM(s3)) {
+ M_IADD_IMM(s3, d);
+ } else {
+ ICONST(REG_ITMP1, -1);
+ M_SRL_IMM(32 - iptr->sx.val.i, REG_ITMP1);
+ M_IADD(REG_ITMP1, d);
+ }
- if (IS_INMEMORY(dst->flags)) {
- M_LST(RDX, REG_SP, dst->vv.regoff * 8);
- M_MOV(REG_ITMP2, RDX); /* restore %rdx */
+ N_BRC_BACK_PATCH(ref);
- } else {
- M_INTMOVE(RDX, dst->vv.regoff);
+ M_SRA_IMM(iptr->sx.val.i, d);
- if (dst->vv.regoff != RDX) {
- M_MOV(REG_ITMP2, RDX); /* restore %rdx */
- }
+ emit_store_dst(jd, iptr, d);
}
-#endif
- break;
- case ICMD_LDIVPOW2: /* ..., value ==> ..., value >> constant */
- /* sx.val.i = constant */
- OOPS();
-#if 0
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
- M_INTMOVE(s1, REG_ITMP1);
- emit_alu_imm_reg(cd, ALU_CMP, -1, REG_ITMP1);
- emit_lea_membase_reg(cd, REG_ITMP1, (1 << iptr->sx.val.i) - 1, REG_ITMP2);
- emit_cmovcc_reg_reg(cd, CC_LE, REG_ITMP2, REG_ITMP1);
- emit_shift_imm_reg(cd, SHIFT_SAR, iptr->sx.val.i, REG_ITMP1);
- emit_mov_reg_reg(cd, REG_ITMP1, d);
- emit_store_dst(jd, iptr, d);
-#endif
break;
+
+ case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
+ /* sx.val.i = constant */
- case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
- /* sx.val.l = constant */
- OOPS();
-#if 0
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
- M_INTMOVE(s1, REG_ITMP1);
- emit_alu_imm_reg(cd, ALU_CMP, -1, REG_ITMP1);
- emit_lea_membase_reg(cd, REG_ITMP1, iptr->sx.val.i, REG_ITMP2);
- emit_cmovcc_reg_reg(cd, CC_G, REG_ITMP1, REG_ITMP2);
- emit_alu_imm_reg(cd, ALU_AND, -1 - (iptr->sx.val.i), REG_ITMP2);
- emit_alu_reg_reg(cd, ALU_SUB, REG_ITMP2, REG_ITMP1);
- emit_mov_reg_reg(cd, REG_ITMP1, d);
- emit_store_dst(jd, iptr, d);
-#endif
- break;
+ d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
- case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
- OOPS();
-#if 0
- d = codegen_reg_of_dst(jd, iptr, REG_NULL);
- emit_ishift(jd, SHIFT_SHL, iptr);
-#endif
- break;
+ if (s1 == d) {
+ M_MOV(s1, REG_ITMP1);
+ s1 = REG_ITMP1;
+ }
+
+ ICONST(REG_ITMP3, iptr->sx.val.i);
- case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
- /* sx.val.i = constant */
- OOPS();
-#if 0
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
M_INTMOVE(s1, d);
- M_ISLL_IMM(iptr->sx.val.i, d);
- emit_store_dst(jd, iptr, d);
-#endif
- break;
+ M_IAND(REG_ITMP3, d);
- case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
- OOPS();
-#if 0
- d = codegen_reg_of_dst(jd, iptr, REG_NULL);
- emit_ishift(jd, SHIFT_SAR, iptr);
-#endif
- break;
+ M_TEST(s1);
+ M_BGE(SZ_BRC + SZ_LCR + SZ_NR + SZ_LCR);
+
+ N_LCR(d, s1);
+ N_NR(d, REG_ITMP3);
+ N_LCR(d, d);
- case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
- /* sx.val.i = constant */
- OOPS();
-#if 0
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
- M_INTMOVE(s1, d);
- M_ISRA_IMM(iptr->sx.val.i, d);
emit_store_dst(jd, iptr, d);
-#endif
- break;
- case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
- OOPS();
-#if 0
- d = codegen_reg_of_dst(jd, iptr, REG_NULL);
- emit_ishift(jd, SHIFT_SHR, iptr);
-#endif
break;
+ case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
+ /* sx.val.i = constant */
+ case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
+ /* sx.val.i = constant */
case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
/* sx.val.i = constant */
- OOPS();
-#if 0
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+ d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+
M_INTMOVE(s1, d);
- M_ISRL_IMM(iptr->sx.val.i, d);
- emit_store_dst(jd, iptr, d);
-#endif
- break;
- case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
- OOPS();
-#if 0
- d = codegen_reg_of_dst(jd, iptr, REG_NULL);
- emit_lshift(jd, SHIFT_SHL, iptr);
-#endif
- break;
+ disp = iptr->sx.val.i & 0x1F; /* Use only 5 bits of value */
+
+ switch (iptr->opc) {
+ case ICMD_ISHLCONST:
+ N_SLL(d, disp, RN);
+ break;
+ case ICMD_ISHRCONST:
+ N_SRA(d, disp, RN);
+ break;
+ case ICMD_IUSHRCONST:
+ N_SRL(d, disp, RN);
+ break;
+ default:
+ assert(0);
+ }
- case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
- /* sx.val.i = constant */
- OOPS();
-#if 0
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
- M_INTMOVE(s1, d);
- M_LSLL_IMM(iptr->sx.val.i, d);
emit_store_dst(jd, iptr, d);
-#endif
break;
+ case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
+
case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
- OOPS();
-#if 0
- d = codegen_reg_of_dst(jd, iptr, REG_NULL);
- emit_lshift(jd, SHIFT_SAR, iptr);
-#endif
- break;
- case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
- /* sx.val.i = constant */
- OOPS();
-#if 0
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
- M_INTMOVE(s1, d);
- M_LSRA_IMM(iptr->sx.val.i, d);
+ case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
+
+ s2 = emit_load_s2(jd, iptr, REG_ITMP3); /* d wont contain REG_ITMP3 */
+
+ /* Use only 6 bits of second operand */
+
+ M_INTMOVE(s2, REG_ITMP3);
+ s2 = REG_ITMP3;
+ ICONST(REG_ITMP2, 0x3F);
+ M_IAND(REG_ITMP2, s2);
+
+ d = emit_alloc_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
+
+ if ((s2 == GET_LOW_REG(d)) || (s2 == GET_HIGH_REG(d))) {
+ M_INTMOVE(s2, REG_ITMP3);
+ s2 = REG_ITMP3;
+ }
+
+ s1 = emit_load_s1(jd, iptr, d);
+
+ M_LNGMOVE(s1, d);
+
+ switch (iptr->opc) {
+ case ICMD_LSHL:
+ M_SLDL(s2, GET_HIGH_REG(d));
+ break;
+ case ICMD_LSHR:
+ M_SRDA(s2, GET_HIGH_REG(d));
+ break;
+ case ICMD_LUSHR:
+ M_SRDL(s2, GET_HIGH_REG(d));
+ break;
+ default:
+ assert(0);
+ }
+
+ emit_copy_dst(jd, iptr, d);
emit_store_dst(jd, iptr, d);
-#endif
- break;
+ emit_restore_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
- case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
- OOPS();
-#if 0
- d = codegen_reg_of_dst(jd, iptr, REG_NULL);
- emit_lshift(jd, SHIFT_SHR, iptr);
-#endif
break;
+ case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
+ /* sx.val.i = constant */
+ case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
+ /* sx.val.i = constant */
case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
/* sx.val.l = constant */
- OOPS();
-#if 0
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
- M_INTMOVE(s1, d);
- M_LSRL_IMM(iptr->sx.val.i, d);
- emit_store_dst(jd, iptr, d);
-#endif
- break;
+ case ICMD_LMULPOW2:
+
+ d = emit_alloc_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2); /* won't contain itmp3 */
+ s1 = emit_load_s1(jd, iptr, d);
+
+ M_LNGMOVE(s1, d);
- case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
- OOPS();
-#if 0
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
- if (s2 == d)
- M_IAND(s1, d);
- else {
- M_INTMOVE(s1, d);
- M_IAND(s2, d);
+ disp = iptr->sx.val.i & 0x3F; /* Use only 6 bits of operand */
+
+ switch (iptr->opc) {
+ case ICMD_LSHLCONST:
+ N_SLDL(GET_HIGH_REG(d), disp, RN);
+ break;
+ case ICMD_LSHRCONST:
+ N_SRDA(GET_HIGH_REG(d), disp, RN);
+ break;
+ case ICMD_LUSHRCONST:
+ N_SRDL(GET_HIGH_REG(d), disp, RN);
+ break;
+ case ICMD_LMULPOW2:
+ N_SLDL(GET_HIGH_REG(d), disp, RN);
+ break;
+ default:
+ assert(0);
}
- emit_store_dst(jd, iptr, d);
-#endif
- break;
- case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
- /* sx.val.i = constant */
- OOPS();
-#if 0
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
- M_INTMOVE(s1, d);
- M_IAND_IMM(iptr->sx.val.i, d);
+ emit_copy_dst(jd, iptr, d);
emit_store_dst(jd, iptr, d);
-#endif
+ emit_restore_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
+
break;
- case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
- OOPS();
-#if 0
+ case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
+
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 (s2 == d)
- M_LAND(s1, d);
+ M_IAND(s1, d);
else {
M_INTMOVE(s1, d);
- M_LAND(s2, d);
+ M_IAND(s2, d);
}
emit_store_dst(jd, iptr, d);
-#endif
- break;
- case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
- /* sx.val.l = constant */
- OOPS();
-#if 0
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
- M_INTMOVE(s1, d);
- if (IS_IMM32(iptr->sx.val.l))
- M_LAND_IMM(iptr->sx.val.l, d);
- else {
- M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
- M_LAND(REG_ITMP2, d);
- }
- emit_store_dst(jd, iptr, d);
-#endif
break;
case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
- OOPS();
-#if 0
+
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
M_IOR(s2, d);
}
emit_store_dst(jd, iptr, d);
-#endif
- break;
-
- case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
- /* sx.val.i = constant */
- OOPS();
-#if 0
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
- M_INTMOVE(s1, d);
- M_IOR_IMM(iptr->sx.val.i, d);
- emit_store_dst(jd, iptr, d);
-#endif
- break;
-
- case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
- OOPS();
-#if 0
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
- if (s2 == d)
- M_LOR(s1, d);
- else {
- M_INTMOVE(s1, d);
- M_LOR(s2, d);
- }
- emit_store_dst(jd, iptr, d);
-#endif
- break;
- case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
- /* sx.val.l = constant */
- OOPS();
-#if 0
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
- M_INTMOVE(s1, d);
- if (IS_IMM32(iptr->sx.val.l))
- M_LOR_IMM(iptr->sx.val.l, d);
- else {
- M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
- M_LOR(REG_ITMP2, d);
- }
- emit_store_dst(jd, iptr, d);
-#endif
break;
case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
- OOPS();
-#if 0
+
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
M_IXOR(s2, d);
}
emit_store_dst(jd, iptr, d);
-#endif
+
break;
+
+
+ case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
+ /* sx.val.i = constant */
+ case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
+ /* sx.val.i = constant */
case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
/* sx.val.i = constant */
- OOPS();
-#if 0
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+
d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+ s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+
M_INTMOVE(s1, d);
- M_IXOR_IMM(iptr->sx.val.i, d);
+ ICONST(REG_ITMP2, iptr->sx.val.i);
+
+ switch (iptr->opc) {
+ case ICMD_IANDCONST:
+ M_IAND(REG_ITMP2, d);
+ break;
+ case ICMD_IXORCONST:
+ M_IXOR(REG_ITMP2, d);
+ break;
+ case ICMD_IORCONST:
+ M_IOR(REG_ITMP2, d);
+ break;
+ default:
+ assert(0);
+ }
+
emit_store_dst(jd, iptr, d);
-#endif
+
break;
+ case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
- OOPS();
-#if 0
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
- if (s2 == d)
- M_LXOR(s1, d);
- else {
- M_INTMOVE(s1, d);
- M_LXOR(s2, d);
+ case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
+
+ d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
+
+ s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
+ s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
+ dd = GET_LOW_REG(d);
+
+ switch (iptr->opc) {
+ case ICMD_LAND:
+ if (s2 == dd) {
+ M_IAND(s1, dd);
+ } else {
+ M_INTMOVE(s1, dd);
+ M_IAND(s2, dd);
+ }
+ break;
+ case ICMD_LXOR:
+ if (s2 == dd) {
+ M_IXOR(s1, dd);
+ } else {
+ M_INTMOVE(s1, dd);
+ M_IXOR(s2, dd);
+ }
+ break;
+ case ICMD_LOR:
+ if (s2 == dd) {
+ M_IOR(s1, dd);
+ } else {
+ M_INTMOVE(s1, dd);
+ M_IOR(s2, dd);
+ }
+ break;
+ default:
+ assert(0);
+ }
+
+ s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
+ s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
+ dd = GET_HIGH_REG(d);
+
+ switch (iptr->opc) {
+ case ICMD_LAND:
+ if (s2 == dd) {
+ M_IAND(s1, dd);
+ } else {
+ M_INTMOVE(s1, dd);
+ M_IAND(s2, dd);
+ }
+ break;
+ case ICMD_LXOR:
+ if (s2 == dd) {
+ M_IXOR(s1, dd);
+ } else {
+ M_INTMOVE(s1, dd);
+ M_IXOR(s2, dd);
+ }
+ break;
+ case ICMD_LOR:
+ if (s2 == dd) {
+ M_IOR(s1, dd);
+ } else {
+ M_INTMOVE(s1, dd);
+ M_IOR(s2, dd);
+ }
+ break;
+ default:
+ assert(0);
}
+
emit_store_dst(jd, iptr, d);
-#endif
break;
+ case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
+ /* sx.val.l = constant */
case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
/* sx.val.l = constant */
- OOPS();
-#if 0
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
- M_INTMOVE(s1, d);
- if (IS_IMM32(iptr->sx.val.l))
- M_LXOR_IMM(iptr->sx.val.l, d);
- else {
- M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
- M_LXOR(REG_ITMP2, d);
+ case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
+ /* sx.val.l = constant */
+
+ /* TODO should use memory operand to access data segment, not load */
+
+ d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
+
+ s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(d));
+ s3 = iptr->sx.val.l & 0xffffffff;
+
+ M_INTMOVE(s1, GET_LOW_REG(d));
+
+ ICONST(REG_ITMP3, s3);
+
+ switch (iptr->opc) {
+ case ICMD_LANDCONST:
+ M_IAND(REG_ITMP3, GET_LOW_REG(d));
+ break;
+ case ICMD_LXORCONST:
+ M_IXOR(REG_ITMP3, GET_LOW_REG(d));
+ break;
+ case ICMD_LORCONST:
+ M_IOR(REG_ITMP3, GET_LOW_REG(d));
+ break;
+ default:
+ assert(0);
+ }
+
+ s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(d));
+ s3 = iptr->sx.val.l >> 32;
+
+ M_INTMOVE(s1, GET_HIGH_REG(d));
+
+ ICONST(REG_ITMP3, s3);
+
+ switch (iptr->opc) {
+ case ICMD_LANDCONST:
+ M_IAND(REG_ITMP3, GET_HIGH_REG(d));
+ break;
+ case ICMD_LXORCONST:
+ M_IXOR(REG_ITMP3, GET_HIGH_REG(d));
+ break;
+ case ICMD_LORCONST:
+ M_IOR(REG_ITMP3, GET_HIGH_REG(d));
+ break;
+ default:
+ assert(0);
}
+
emit_store_dst(jd, iptr, d);
-#endif
- break;
+ break;
/* floating operations ************************************************/
case ICMD_FNEG: /* ..., value ==> ..., - value */
- OOPS();
-#if 0
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
- d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
- disp = dseg_add_s4(cd, 0x80000000);
- M_FLTMOVE(s1, d);
- emit_movss_membase_reg(cd, RIP, -((cd->mcodeptr + 9) - cd->mcodebase) + disp, REG_FTMP2);
- emit_xorps_reg_reg(cd, REG_FTMP2, d);
+ d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
+ M_FMOVN(s1, d);
emit_store_dst(jd, iptr, d);
-#endif
break;
case ICMD_DNEG: /* ..., value ==> ..., - value */
- OOPS();
-#if 0
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
- d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
- disp = dseg_add_s8(cd, 0x8000000000000000);
- M_FLTMOVE(s1, d);
- emit_movd_membase_reg(cd, RIP, -((cd->mcodeptr + 9) - cd->mcodebase) + disp, REG_FTMP2);
- emit_xorpd_reg_reg(cd, REG_FTMP2, d);
+ d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
+ M_DMOVN(s1, d);
emit_store_dst(jd, iptr, d);
-#endif
break;
case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
- OOPS();
-#if 0
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
s2 = emit_load_s2(jd, iptr, REG_FTMP2);
- d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
+ d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
if (s2 == d)
M_FADD(s1, d);
else {
M_FADD(s2, d);
}
emit_store_dst(jd, iptr, d);
-#endif
break;
case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
- OOPS();
-#if 0
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
s2 = emit_load_s2(jd, iptr, REG_FTMP2);
- d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
+ d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
if (s2 == d)
M_DADD(s1, d);
else {
M_DADD(s2, d);
}
emit_store_dst(jd, iptr, d);
-#endif
break;
case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
- OOPS();
-#if 0
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
- s2 = emit_load_s2(jd, iptr, REG_FTMP2);
- d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
- if (s2 == d) {
- M_FLTMOVE(s2, REG_FTMP2);
- s2 = REG_FTMP2;
- }
+ d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
+ s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
+
M_FLTMOVE(s1, d);
M_FSUB(s2, d);
emit_store_dst(jd, iptr, d);
-#endif
break;
case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
- OOPS();
-#if 0
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
- s2 = emit_load_s2(jd, iptr, REG_FTMP2);
- d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
- if (s2 == d) {
- M_FLTMOVE(s2, REG_FTMP2);
- s2 = REG_FTMP2;
- }
+ d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
+ s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
+
M_FLTMOVE(s1, d);
M_DSUB(s2, d);
emit_store_dst(jd, iptr, d);
-#endif
break;
case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
s2 = emit_load_s2(jd, iptr, REG_FTMP2);
- d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
+ d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
if (s2 == d)
M_FMUL(s1, d);
else {
M_FMUL(s2, d);
}
emit_store_dst(jd, iptr, d);
-
break;
case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
- OOPS();
-#if 0
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
s2 = emit_load_s2(jd, iptr, REG_FTMP2);
- d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
+ d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
if (s2 == d)
M_DMUL(s1, d);
else {
M_DMUL(s2, d);
}
emit_store_dst(jd, iptr, d);
-#endif
break;
case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
- OOPS();
-#if 0
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
- s2 = emit_load_s2(jd, iptr, REG_FTMP2);
- d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
- if (s2 == d) {
- M_FLTMOVE(s2, REG_FTMP2);
- s2 = REG_FTMP2;
- }
+ d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
+ s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
+
M_FLTMOVE(s1, d);
M_FDIV(s2, d);
emit_store_dst(jd, iptr, d);
-#endif
break;
case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
- OOPS();
-#if 0
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
- s2 = emit_load_s2(jd, iptr, REG_FTMP2);
- d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
- if (s2 == d) {
- M_FLTMOVE(s2, REG_FTMP2);
- s2 = REG_FTMP2;
- }
+ d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
+ s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
+
M_FLTMOVE(s1, d);
M_DDIV(s2, d);
emit_store_dst(jd, iptr, d);
-#endif
break;
case ICMD_I2F: /* ..., value ==> ..., (float) value */
emit_store_dst(jd, iptr, d);
break;
- case ICMD_L2F: /* ..., value ==> ..., (float) value */
- OOPS();
-#if 0
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
- M_CVTLF(s1, d);
- emit_store_dst(jd, iptr, d);
-#endif
- break;
-
- case ICMD_L2D: /* ..., value ==> ..., (double) value */
- OOPS();
-#if 0
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
- M_CVTLD(s1, d);
- emit_store_dst(jd, iptr, d);
-#endif
- break;
-
case ICMD_F2I: /* ..., value ==> ..., (int) value */
- s1 = emit_load_s1(jd, iptr, REG_FTMP1);
- d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
- M_CVTFI(s1, d);
- emit_store_dst(jd, iptr, d);
- /* TODO: corner cases ? */
- break;
-
- case ICMD_D2I: /* ..., value ==> ..., (int) value */
- OOPS();
-#if 0
- s1 = emit_load_s1(jd, iptr, REG_FTMP1);
- d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
- M_CVTDI(s1, d);
- M_ICMP_IMM(0x80000000, d); /* corner cases */
- disp = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 +
- ((REG_RESULT == d) ? 0 : 3);
- M_BNE(disp);
- M_FLTMOVE(s1, REG_FTMP1);
- M_MOV_IMM(asm_builtin_d2i, REG_ITMP2);
- M_CALL(REG_ITMP2);
- M_INTMOVE(REG_RESULT, d);
- emit_store_dst(jd, iptr, d);
+ case ICMD_D2I:
+ {
+ u1 *ref1;
+#ifdef SUPPORT_HERCULES
+ u1 *ref2, *ref3;
#endif
- break;
- case ICMD_F2L: /* ..., value ==> ..., (long) value */
- OOPS();
-#if 0
- s1 = emit_load_s1(jd, iptr, REG_FTMP1);
- d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
- M_CVTFL(s1, d);
- M_MOV_IMM(0x8000000000000000, REG_ITMP2);
- M_LCMP(REG_ITMP2, d); /* corner cases */
- disp = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 +
- ((REG_RESULT == d) ? 0 : 3);
- M_BNE(disp);
- M_FLTMOVE(s1, REG_FTMP1);
- M_MOV_IMM(asm_builtin_f2l, REG_ITMP2);
- M_CALL(REG_ITMP2);
- M_INTMOVE(REG_RESULT, d);
- emit_store_dst(jd, iptr, d);
-#endif
- break;
+ s1 = emit_load_s1(jd, iptr, REG_FTMP1);
+ d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
- case ICMD_D2L: /* ..., value ==> ..., (long) value */
- OOPS();
-#if 0
- s1 = emit_load_s1(jd, iptr, REG_FTMP1);
- d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
- M_CVTDL(s1, d);
- M_MOV_IMM(0x8000000000000000, REG_ITMP2);
- M_LCMP(REG_ITMP2, d); /* corner cases */
- disp = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 +
- ((REG_RESULT == d) ? 0 : 3);
- M_BNE(disp);
- M_FLTMOVE(s1, REG_FTMP1);
- M_MOV_IMM(asm_builtin_d2l, REG_ITMP2);
- M_CALL(REG_ITMP2);
- M_INTMOVE(REG_RESULT, d);
- emit_store_dst(jd, iptr, d);
+ /* Test if NAN */
+
+ switch (iptr->opc) {
+ case ICMD_F2I:
+ N_LTEBR(s1, s1);
+ break;
+ case ICMD_D2I:
+ N_LTDBR(s1, s1);
+ break;
+ }
+
+ N_BRC(DD_0 | DD_1 | DD_2, SZ_BRC + SZ_LHI + SZ_BRC); /* Non a NaN */
+ N_LHI(d, 0); /* Load 0 */
+ ref1 = cd->mcodeptr;
+ N_BRC(DD_ANY, 0); /* Exit */
+
+ /* Convert */
+
+ switch (iptr->opc) {
+ case ICMD_F2I:
+ M_CVTFI(s1, d);
+ break;
+ case ICMD_D2I:
+ M_CVTDI(s1, d);
+ break;
+ }
+
+#ifdef SUPPORT_HERCULES
+ /* Hercules does the conversion using a plain C conversion.
+ * According to manual, real hardware should *NOT* require this.
+ *
+ * Corner case: Positive float leads to INT_MIN (overflow).
+ */
+
+ switch (iptr->opc) {
+ case ICMD_F2I:
+ N_LTEBR(s1, s1);
+ break;
+ case ICMD_D2I:
+ N_LTDBR(s1, s1);
+ break;
+ }
+
+ ref2 = cd->mcodeptr;
+ N_BRC(DD_0 | DD_1 | DD_3, 0); /* If operand is positive, continue */
+
+ M_TEST(d);
+
+ ref3 = cd->mcodeptr;
+ M_BGE(0); /* If integer result is negative, continue */
+
+ disp = dseg_add_s4(cd, 0x7fffffff); /* Load INT_MAX */
+ M_ILD_DSEG(d, disp);
+#endif
+ N_BRC_BACK_PATCH(ref1);
+#ifdef SUPPORT_HERCULES
+ N_BRC_BACK_PATCH(ref2);
+ N_BRC_BACK_PATCH(ref3);
#endif
+ emit_store_dst(jd, iptr, d);
+ }
break;
case ICMD_F2D: /* ..., value ==> ..., (double) value */
- OOPS();
-#if 0
- s1 = emit_load_s1(jd, iptr, REG_FTMP1);
- d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
- M_CVTFD(s1, d);
- emit_store_dst(jd, iptr, d);
+ {
+ u1 *ref;
+ s1 = emit_load_s1(jd, iptr, REG_FTMP1);
+ d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
+#ifdef SUPPORT_HERCULES
+ N_LTEBR(s1, s1);
+ ref = cd->mcodeptr;
+ N_BRC(DD_0 | DD_1 | DD_2, 0); /* Non a NaN */
+ disp = dseg_add_double(cd, 0.0 / 0.0);
+ M_DLD_DSEG(d, disp, REG_ITMP1);
+ emit_label_br(cd, BRANCH_LABEL_1);
+ N_BRC_BACK_PATCH(ref);
+#endif
+ M_CVTFD(s1, d);
+#ifdef SUPPORT_HERCULES
+ emit_label(cd, BRANCH_LABEL_1);
#endif
+ emit_store_dst(jd, iptr, d);
+ }
break;
case ICMD_D2F: /* ..., value ==> ..., (float) value */
- OOPS();
-#if 0
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
- d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
+ d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
M_CVTDF(s1, d);
emit_store_dst(jd, iptr, d);
-#endif
break;
case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
/* == => 0, < => 1, > => -1 */
- /* ICMD_FCMPL: s1 < s2 -> d := 1 */ /* TODO is this correct ? */
+ case ICMD_DCMPL:
case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
/* == => 0, < => 1, > => -1 */
+ case ICMD_DCMPG:
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
s2 = emit_load_s2(jd, iptr, REG_FTMP2);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
- N_CEBR(s1, s2);
+ switch (iptr->opc) {
+ case ICMD_FCMPG:
+ case ICMD_FCMPL:
+ M_FCMP(s1, s2);
+ break;
+ case ICMD_DCMPG:
+ case ICMD_DCMPL:
+ M_DCMP(s1, s2);
+ break;
+ }
- M_BGT(SZ_BR + SZ_BR + SZ_BR);
- M_BLT(SZ_BR + SZ_BR + SZ_LHI + SZ_BR);
- M_BEQ(SZ_BR + SZ_LHI + SZ_BR + SZ_LHI + SZ_BR);
+ N_BRC( /* load 1 */
+ DD_H | (iptr->opc == ICMD_FCMPG || iptr->opc == ICMD_DCMPG ? DD_O : 0),
+ SZ_BRC + SZ_BRC + SZ_BRC
+ );
- N_LHI(d, iptr->opc == ICMD_FCMPL ? -1 : 1); /* s1 > s2 */
- M_BR(SZ_BR + SZ_LHI + SZ_BR + SZ_LHI);
- N_LHI(d, iptr->opc == ICMD_FCMPL ? 1 : -1); /* s1 < s2 */
- M_BR(SZ_BR + SZ_LHI);
- N_LHI(d, 0); /* s1 == s2 */
+ N_BRC( /* load -1 */
+ DD_L | (iptr->opc == ICMD_FCMPL || iptr->opc == ICMD_DCMPL ? DD_O : 0),
+ SZ_BRC + SZ_BRC + SZ_LHI + SZ_BRC
+ );
- emit_store_dst(jd, iptr, d);
+ N_BRC( /* load 0 */
+ DD_E,
+ SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI + SZ_BRC
+ );
- break;
+ N_LHI(d, 1); /* GT */
+ M_BR(SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI);
+ N_LHI(d, -1); /* LT */
+ M_BR(SZ_BRC + SZ_LHI);
+ N_LHI(d, 0); /* EQ */
- case ICMD_DCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
- /* == => 0, < => 1, > => -1 */
- OOPS();
-#if 0
- s1 = emit_load_s1(jd, iptr, REG_FTMP1);
- s2 = emit_load_s2(jd, iptr, REG_FTMP2);
- d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
- M_CLR(d);
- M_MOV_IMM(1, REG_ITMP1);
- M_MOV_IMM(-1, REG_ITMP2);
- emit_ucomisd_reg_reg(cd, s1, s2);
- M_CMOVB(REG_ITMP1, d);
- M_CMOVA(REG_ITMP2, d);
- M_CMOVP(REG_ITMP2, d); /* treat unordered as GT */
emit_store_dst(jd, iptr, d);
-#endif
- break;
- case ICMD_DCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
- /* == => 0, < => 1, > => -1 */
- OOPS();
-#if 0
- s1 = emit_load_s1(jd, iptr, REG_FTMP1);
- s2 = emit_load_s2(jd, iptr, REG_FTMP2);
- d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
- M_CLR(d);
- M_MOV_IMM(1, REG_ITMP1);
- M_MOV_IMM(-1, REG_ITMP2);
- emit_ucomisd_reg_reg(cd, s1, s2);
- M_CMOVB(REG_ITMP1, d);
- M_CMOVA(REG_ITMP2, d);
- M_CMOVP(REG_ITMP1, d); /* treat unordered as LT */
- emit_store_dst(jd, iptr, d);
-#endif
break;
case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., (int) length */
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+ s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
- gen_nullptr_check(s1);
- M_ILD(d, s1, OFFSET(java_arrayheader, size));
+ /* TODO softnull */
+ /* implicit null-pointer check */
+ M_ILD(d, s1, OFFSET(java_array_t, size));
emit_store_dst(jd, iptr, d);
break;
case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
- OOPS();
-#if 0
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
- }
- emit_movsbq_memindex_reg(cd, OFFSET(java_bytearray, data[0]), s1, s2, 0, d);
+ s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
+ s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
+ d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+
+ /* implicit null-pointer check */
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
+
+ N_IC(d, OFFSET(java_bytearray_t, data[0]), s2, s1);
+
+ M_SLL_IMM(24, d);
+ M_SRA_IMM(24, d);
+
emit_store_dst(jd, iptr, d);
-#endif
break;
case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
- OOPS();
-#if 0
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+
+ s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
- }
- emit_movzwq_memindex_reg(cd, OFFSET(java_chararray, data[0]), s1, s2, 1, d);
+ d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+
+ /* implicit null-pointer check */
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
+
+ M_INTMOVE(s2, REG_ITMP2);
+ M_SLL_IMM(1, REG_ITMP2);
+
+ N_LH(d, OFFSET(java_chararray_t, data[0]), REG_ITMP2, s1);
+
+ /* N_LH does sign extends, undo ! */
+
+ M_SLL_IMM(16, d);
+ M_SRL_IMM(16, d);
+
emit_store_dst(jd, iptr, d);
-#endif
break;
case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
- OOPS();
-#if 0
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+ s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
- }
- emit_movswq_memindex_reg(cd, OFFSET(java_shortarray, data[0]), s1, s2, 1, d);
+ d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+
+ /* implicit null-pointer check */
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
+
+ M_INTMOVE(s2, REG_ITMP2);
+ M_SLL_IMM(1, REG_ITMP2);
+
+ N_LH(d, OFFSET(java_shortarray_t, data[0]), REG_ITMP2, s1);
emit_store_dst(jd, iptr, d);
-#endif
break;
case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
- OOPS();
-#if 0
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+ s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
- }
- emit_movl_memindex_reg(cd, OFFSET(java_intarray, data[0]), s1, s2, 2, d);
+ d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+
+ /* implicit null-pointer check */
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
+
+ M_INTMOVE(s2, REG_ITMP2);
+ M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
+ N_L(d, OFFSET(java_intarray_t, data[0]), REG_ITMP2, s1);
emit_store_dst(jd, iptr, d);
-#endif
break;
case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
- OOPS();
-#if 0
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+
+ s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP3);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
+
+ d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
+
+ /* implicit null-pointer check */
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
+
+ M_INTMOVE(s2, REG_ITMP2);
+ M_SLL_IMM(3, REG_ITMP2); /* scale index by 8 */
+
+ /* We need to preserve the array address after the first load */
+
+ if (GET_HIGH_REG(d) == s1) {
+ M_INTMOVE(s1, REG_ITMP3);
+ s1 = REG_ITMP3;
}
- emit_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]), s1, s2, 3, d);
+
+ N_L(GET_HIGH_REG(d) /* evntl. itmp1 */, OFFSET(java_intarray_t, data[0]), REG_ITMP2, s1);
+ N_L(GET_LOW_REG(d) /* evntl. itmp2 */, OFFSET(java_intarray_t, data[0]) + 4, REG_ITMP2, s1);
emit_store_dst(jd, iptr, d);
-#endif
+
break;
case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
- OOPS();
-#if 0
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+
+ s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
- }
- emit_movss_memindex_reg(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2, d);
+ d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
+
+ /* implicit null-pointer check */
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
+
+ M_INTMOVE(s2, REG_ITMP2);
+ M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
+
+ N_LE(d, OFFSET(java_floatarray_t, data[0]), REG_ITMP2, s1);
+
emit_store_dst(jd, iptr, d);
-#endif
break;
case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
- OOPS();
-#if 0
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+ s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
- }
- emit_movsd_memindex_reg(cd, OFFSET(java_doublearray, data[0]), s1, s2, 3, d);
+ d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
+
+ /* implicit null-pointer check */
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
+
+ M_INTMOVE(s2, REG_ITMP2);
+ M_SLL_IMM(3, REG_ITMP2); /* scale index by 8 */
+
+ N_LD(d, OFFSET(java_floatarray_t, data[0]), REG_ITMP2, s1);
+
emit_store_dst(jd, iptr, d);
-#endif
break;
case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+ s1 = emit_load_s1_notzero(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);
+
+ /* implicit null-pointer check */
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
- M_INTMOVE(s1, REG_ITMP1);
- N_SLL(REG_ITMP1, 2, RN); /* scale index by 4 */
- N_L(d, OFFSET(java_objectarray, data[0]), REG_ITMP1, s2);
+ M_INTMOVE(s2, REG_ITMP2);
+ M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
+ N_L(d, OFFSET(java_objectarray_t, data[0]), REG_ITMP2, s1);
emit_store_dst(jd, iptr, d);
break;
case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
- OOPS();
-#if 0
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
- }
- s3 = emit_load_s3(jd, iptr, REG_ITMP3);
- emit_movb_reg_memindex(cd, s3, OFFSET(java_bytearray, data[0]), s1, s2, 0);
-#endif
- break;
-
- case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
- OOPS();
-#if 0
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
- }
+ s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
+ s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
+ /* implicit null-pointer check */
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
s3 = emit_load_s3(jd, iptr, REG_ITMP3);
- emit_movw_reg_memindex(cd, s3, OFFSET(java_chararray, data[0]), s1, s2, 1);
-#endif
- break;
- case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
- OOPS();
-#if 0
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
- }
- s3 = emit_load_s3(jd, iptr, REG_ITMP3);
- emit_movw_reg_memindex(cd, s3, OFFSET(java_shortarray, data[0]), s1, s2, 1);
-#endif
+ N_STC(s3, OFFSET(java_bytearray_t, data[0]), s2, s1);
break;
- case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
- OOPS();
-#if 0
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
- }
- s3 = emit_load_s3(jd, iptr, REG_ITMP3);
- emit_movl_reg_memindex(cd, s3, OFFSET(java_intarray, data[0]), s1, s2, 2);
-#endif
- break;
+ case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
- case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
- OOPS();
-#if 0
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+ s1 = emit_load_s1_notzero(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);
- emit_mov_reg_memindex(cd, s3, OFFSET(java_longarray, data[0]), s1, s2, 3);
-#endif
- break;
-
- case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
- OOPS();
-#if 0
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
- }
- s3 = emit_load_s3(jd, iptr, REG_FTMP3);
- emit_movss_reg_memindex(cd, s3, OFFSET(java_floatarray, data[0]), s1, s2, 2);
-#endif
- break;
-
- case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
- OOPS();
-#if 0
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
- }
- s3 = emit_load_s3(jd, iptr, REG_FTMP3);
- emit_movsd_reg_memindex(cd, s3, OFFSET(java_doublearray, data[0]), s1, s2, 3);
-#endif
- break;
- case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
- OOPS();
-#if 0
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
- }
- s3 = emit_load_s3(jd, iptr, REG_ITMP3);
+ M_INTMOVE(s2, REG_ITMP2);
+ M_SLL_IMM(1, REG_ITMP2);
- M_MOV(s1, REG_A0);
- M_MOV(s3, REG_A1);
- M_MOV_IMM(BUILTIN_canstore, REG_ITMP1);
- M_CALL(REG_ITMP1);
- M_TEST(REG_RESULT);
- M_BEQ(0);
- codegen_add_arraystoreexception_ref(cd);
+ N_STH(s3, OFFSET(java_chararray_t, data[0]), REG_ITMP2, s1);
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+ break;
+
+ case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
+ s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+ /* implicit null-pointer check */
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
s3 = emit_load_s3(jd, iptr, REG_ITMP3);
- emit_mov_reg_memindex(cd, s3, OFFSET(java_objectarray, data[0]), s1, s2, 3);
-#endif
+
+ M_INTMOVE(s2, REG_ITMP2);
+ M_SLL_IMM(1, REG_ITMP2);
+
+ N_STH(s3, OFFSET(java_shortarray_t, data[0]), REG_ITMP2, s1);
break;
+ case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
- case ICMD_BASTORECONST: /* ..., arrayref, index ==> ... */
- OOPS();
-#if 0
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+ s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
- }
- emit_movb_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_bytearray, data[0]), s1, s2, 0);
-#endif
+ /* implicit null-pointer check */
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
+
+ s3 = emit_load_s3(jd, iptr, REG_ITMP3);
+
+ M_INTMOVE(s2, REG_ITMP2);
+ M_SLL_IMM(2, REG_ITMP2);
+
+ N_ST(s3, OFFSET(java_intarray_t, data[0]), REG_ITMP2, s1);
break;
- case ICMD_CASTORECONST: /* ..., arrayref, index ==> ... */
- OOPS();
-#if 0
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+ case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
+
+ s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
- }
- emit_movw_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_chararray, data[0]), s1, s2, 1);
-#endif
+ /* implicit null-pointer check */
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
+
+ M_INTMOVE(s2, REG_ITMP2);
+ M_SLL_IMM(3, REG_ITMP2);
+
+ s3 = emit_load_s3_high(jd, iptr, REG_ITMP3);
+ N_ST(s3, OFFSET(java_intarray_t, data[0]), REG_ITMP2, s1);
+ s3 = emit_load_s3_low(jd, iptr, REG_ITMP3);
+ N_ST(s3, OFFSET(java_intarray_t, data[0]) + 4, REG_ITMP2, s1);
break;
- case ICMD_SASTORECONST: /* ..., arrayref, index ==> ... */
- OOPS();
-#if 0
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+ case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
+ s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
- }
- emit_movw_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_shortarray, data[0]), s1, s2, 1);
-#endif
+ /* implicit null-pointer check */
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
+ s3 = emit_load_s3(jd, iptr, REG_FTMP1);
+
+ M_INTMOVE(s2, REG_ITMP2);
+ M_SLL_IMM(2, REG_ITMP2);
+
+ N_STE(s3, OFFSET(java_floatarray_t, data[0]), REG_ITMP2, s1);
break;
- case ICMD_IASTORECONST: /* ..., arrayref, index ==> ... */
- OOPS();
-#if 0
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+ case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
+ s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
- }
- emit_movl_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_intarray, data[0]), s1, s2, 2);
-#endif
+ /* implicit null-pointer check */
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
+ s3 = emit_load_s3(jd, iptr, REG_FTMP1);
+
+ M_INTMOVE(s2, REG_ITMP2);
+ M_SLL_IMM(3, REG_ITMP2);
+
+ N_STD(s3, OFFSET(java_doublearray_t, data[0]), REG_ITMP2, s1);
break;
- case ICMD_LASTORECONST: /* ..., arrayref, index ==> ... */
- OOPS();
-#if 0
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+ case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
+
+ s1 = emit_load_s1_notzero(jd, iptr, REG_A0);
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_A1);
- if (IS_IMM32(iptr->sx.s23.s3.constval)) {
- emit_mov_imm_memindex(cd, (u4) (iptr->sx.s23.s3.constval & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
- } else {
- emit_movl_imm_memindex(cd, (u4) (iptr->sx.s23.s3.constval & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
- emit_movl_imm_memindex(cd, (u4) (iptr->sx.s23.s3.constval >> 32), OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
- }
-#endif
- break;
+ M_INTMOVE(s1, REG_A0);
+ M_INTMOVE(s3, REG_A1);
+
+ disp = dseg_add_functionptr(cd, BUILTIN_canstore);
+ M_ALD_DSEG(REG_ITMP3, disp);
+ M_ASUB_IMM(96, REG_SP);
+ M_JSR(REG_RA, REG_ITMP3);
+ M_AADD_IMM(96, REG_SP);
+
+ emit_exception_check(cd, iptr);
- case ICMD_AASTORECONST: /* ..., arrayref, index ==> ... */
- OOPS();
-#if 0
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
- }
- emit_mov_imm_memindex(cd, 0, OFFSET(java_objectarray, data[0]), s1, s2, 3);
-#endif
+ s3 = emit_load_s3(jd, iptr, REG_ITMP3);
+
+ M_INTMOVE(s2, REG_ITMP2);
+ M_SLL_IMM(2, REG_ITMP2);
+ N_ST(s3, OFFSET(java_objectarray_t, data[0]), REG_ITMP2, s1);
+
+ /*
+ M_SAADDQ(s2, s1, REG_ITMP1); itmp1 := 4 * s2 + s1
+ M_AST(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
+ */
break;
/* PROFILE_CYCLE_STOP; */
- codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
+ patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
/* PROFILE_CYCLE_START; */
}
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)) {
PROFILE_CYCLE_STOP;
- codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, 0);
+ patcher_add_patch_ref(jd, PATCHER_clinit, fi->class, 0);
PROFILE_CYCLE_START;
}
}
- M_ALD(REG_ITMP1, REG_PV, disp);
+ M_ALD_DSEG(REG_ITMP1, disp);
switch (fieldtype) {
case TYPE_INT:
M_ILD(d, REG_ITMP1, 0);
break;
case TYPE_LNG:
- d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
+ d = codegen_reg_of_dst(jd, iptr, REG_ITMP23_PACKED);
M_LLD(d, REG_ITMP1, 0);
break;
case TYPE_ADR:
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_clinit,
- fi->class, disp);
+ if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
+ PROFILE_CYCLE_STOP;
+ patcher_add_patch_ref(jd, PATCHER_clinit, fi->class, disp);
+ PROFILE_CYCLE_START;
+ }
}
- M_ALD(REG_ITMP1, REG_PV, disp);
+ M_ALD_DSEG(REG_ITMP1, disp);
switch (fieldtype) {
case TYPE_INT:
s1 = emit_load_s1(jd, iptr, REG_ITMP2);
}
break;
- case ICMD_PUTSTATICCONST: /* ... ==> ... */
- /* val = value (in current instruction) */
- /* following NOP) */
- OOPS();
-#if 0
- if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
- uf = iptr->sx.s23.s3.uf;
- fieldtype = uf->fieldref->parseddesc.fd->type;
- disp = dseg_add_unique_address(cd, uf);
-
- 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 (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
- codegen_add_patch_ref(cd, PATCHER_initialize_class, fi->class,
- 0);
- }
-
- M_ALD(REG_ITMP1, REG_PV, disp);
-
- switch (fieldtype) {
- case TYPE_INT:
- M_IST(REG_ZERO, REG_ITMP1, 0);
- break;
- case TYPE_LNG:
- M_LST(REG_ZERO, REG_ITMP1, 0);
- break;
- case TYPE_ADR:
- M_AST(REG_ZERO, REG_ITMP1, 0);
- break;
- case TYPE_FLT:
- M_FST(REG_ZERO, REG_ITMP1, 0);
- break;
- case TYPE_DBL:
- M_DST(REG_ZERO, REG_ITMP1, 0);
- break;
- }
-#endif
- break;
-
case ICMD_GETFIELD: /* ... ==> ..., value */
- OOPS();
-#if 0
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- gen_nullptr_check(s1);
+
+ s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
+ emit_nullpointer_check(cd, iptr, s1);
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
uf = iptr->sx.s23.s3.uf;
fieldtype = uf->fieldref->parseddesc.fd->type;
disp = 0;
-/* PROFILE_CYCLE_STOP; */
-
- codegen_add_patch_ref(cd, PATCHER_get_putfield, uf, 0);
-
-/* PROFILE_CYCLE_START; */
+ patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
}
else {
fi = iptr->sx.s23.s3.fmiref->p.field;
switch (fieldtype) {
case TYPE_INT:
- d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
- M_ILD32(d, s1, disp);
+ d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+ M_ILD(d, s1, disp);
break;
case TYPE_LNG:
+ d = codegen_reg_of_dst(jd, iptr, REG_ITMP23_PACKED);
+ if (GET_HIGH_REG(d) == s1) {
+ M_ILD(GET_LOW_REG(d), s1, disp + 4);
+ M_ILD(GET_HIGH_REG(d), s1, disp);
+ }
+ else {
+ M_ILD(GET_LOW_REG(d), s1, disp + 4);
+ M_ILD(GET_HIGH_REG(d), s1, disp);
+ }
+ break;
case TYPE_ADR:
- d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
- M_LLD32(d, s1, disp);
+ d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+ M_ALD(d, s1, disp);
break;
case TYPE_FLT:
d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
- M_FLD32(d, s1, disp);
+ M_FLD(d, s1, disp);
break;
case TYPE_DBL:
d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
- M_DLD32(d, s1, disp);
+ M_DLD(d, s1, disp);
break;
}
emit_store_dst(jd, iptr, d);
-#endif
break;
case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
+ {
+ u1 *ref;
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- gen_nullptr_check(s1);
-
- s2 = emit_load_s2(jd, iptr, REG_IFTMP);
+ s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
+ emit_nullpointer_check(cd, iptr, s1);
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
uf = iptr->sx.s23.s3.uf;
disp = fi->offset;
}
+ /* We can't add a patcher ref behind this load,
+ * because the patcher would destroy REG_ITMP3.
+ *
+ * We pass in the disp parameter, how many bytes
+ * to skip to the to the actual store.
+ *
+ * XXX this relies on patcher_add_patch_ref internals
+ */
+
+ if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+ patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
+ ref = cd->mcodeptr;
+ }
+
+
if (IS_INT_LNG_TYPE(fieldtype)) {
if (IS_2_WORD_TYPE(fieldtype))
s2 = emit_load_s2(jd, iptr, REG_ITMP23_PACKED);
else
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- }
- else
+ } else {
s2 = emit_load_s2(jd, iptr, REG_FTMP2);
-
- if (INSTRUCTION_IS_UNRESOLVED(iptr))
- codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0);
-
- switch (fieldtype) {
- case TYPE_INT:
- M_IST(s2, s1, disp);
- break;
- case TYPE_LNG:
- /* TODO really order */
- M_IST(GET_LOW_REG(s2), s1, disp + 4); /* keep this order */
- M_IST(GET_HIGH_REG(s2), s1, disp); /* keep this order */
- break;
- case TYPE_ADR:
- M_AST(s2, s1, disp);
- break;
- case TYPE_FLT:
- M_FST(s2, s1, disp);
- break;
- case TYPE_DBL:
- M_DST(s2, s1, disp);
- break;
}
- break;
-
- case ICMD_PUTFIELDCONST: /* ..., objectref, value ==> ... */
- /* val = value (in current instruction) */
- /* following NOP) */
- OOPS();
-#if 0
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- gen_nullptr_check(s1);
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
- uf = iptr->sx.s23.s3.uf;
- fieldtype = uf->fieldref->parseddesc.fd->type;
- disp = 0;
-
-/* PROFILE_CYCLE_STOP; */
-
- codegen_add_patch_ref(cd, PATCHER_putfieldconst, uf, 0);
-
-/* PROFILE_CYCLE_START; */
- }
- else {
- fi = iptr->sx.s23.s3.fmiref->p.field;
- fieldtype = fi->type;
- disp = fi->offset;
+ ((patchref_t *)list_first_unsynced(jd->code->patchers))->disp = (cd->mcodeptr - ref);
}
switch (fieldtype) {
- case TYPE_INT:
- case TYPE_FLT:
- M_IST32_IMM(iptr->sx.s23.s2.constval, s1, disp);
- break;
- case TYPE_LNG:
- case TYPE_ADR:
- case TYPE_DBL:
- /* XXX why no check for IS_IMM32? */
- M_IST32_IMM(iptr->sx.s23.s2.constval, s1, disp);
- M_IST32_IMM(iptr->sx.s23.s2.constval >> 32, s1, disp + 4);
- break;
+ case TYPE_INT:
+ M_IST(s2, s1, disp);
+ break;
+ case TYPE_LNG:
+ M_IST(GET_LOW_REG(s2), s1, disp + 4); /* keep this order */
+ M_IST(GET_HIGH_REG(s2), s1, disp); /* keep this order */
+ break;
+ case TYPE_ADR:
+ M_AST(s2, s1, disp);
+ break;
+ case TYPE_FLT:
+ M_FST(s2, s1, disp);
+ break;
+ case TYPE_DBL:
+ M_DST(s2, s1, disp);
+ break;
}
-#endif
- break;
+ }
+ break;
/* branch operations **************************************************/
case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
+ /* PROFILE_CYCLE_STOP; */
+
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
M_INTMOVE(s1, REG_ITMP1_XPTR);
- PROFILE_CYCLE_STOP;
-
#ifdef ENABLE_VERIFIER
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
uc = iptr->sx.s23.s2.uc;
- codegen_add_patch_ref(cd, PATCHER_athrow_areturn, uc, 0);
+ patcher_add_patch_ref(jd, PATCHER_athrow_areturn, uc, 0);
}
#endif /* ENABLE_VERIFIER */
disp = dseg_add_functionptr(cd, asm_handle_exception);
- M_ALD(REG_ITMP2, REG_PV, disp);
+ M_ALD_DSEG(REG_ITMP2, disp);
M_JMP(REG_ITMP2_XPC, REG_ITMP2);
M_NOP;
case ICMD_GOTO: /* ... ==> ... */
case ICMD_RET: /* ... ==> ... */
- M_BR(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
+ emit_br(cd, iptr->dst.block);
break;
case ICMD_JSR: /* ... ==> ... */
- OOPS();
-#if 0
- M_JMP_IMM(0);
- codegen_add_branch_ref(cd, iptr->sx.s23.s3.jsrtarget.block);
-#endif
+
+ emit_br(cd, iptr->sx.s23.s3.jsrtarget.block);
+
break;
case ICMD_IFNULL: /* ..., value ==> ... */
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- M_TEST(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_TEST(s1);
- M_BNE(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
+ switch (iptr->opc) {
+ case ICMD_IFNULL:
+ emit_beq(cd, iptr->dst.block);
+ break;
+ case ICMD_IFNONNULL:
+ emit_bne(cd, iptr->dst.block);
+ break;
+ }
break;
case ICMD_IFEQ: /* ..., value ==> ... */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- if ((iptr->sx.val.i >= -32768) && (iptr->sx.val.i <= 32767))
- N_CHI(s1, iptr->sx.val.i);
+ if (N_VALID_IMM(iptr->sx.val.i))
+ M_ICMP_IMM(s1, iptr->sx.val.i);
else {
disp = dseg_add_s4(cd, iptr->sx.val.i);
- N_LHI(REG_ITMP2, disp);
- N_CL(s1, 0, REG_ITMP2, REG_PV);
+ if (N_VALID_DSEG_DISP(disp)) {
+ N_C(s1, N_DSEG_DISP(disp), RN, REG_PV);
+ } else {
+ ICONST(REG_ITMP2, disp);
+ N_C(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
+ }
}
switch (iptr->opc) {
case ICMD_IFLT:
- M_BLT(0);
+ emit_blt(cd, iptr->dst.block);
break;
case ICMD_IFLE:
- M_BLE(0);
+ emit_ble(cd, iptr->dst.block);
break;
case ICMD_IFNE:
- M_BNE(0);
+ emit_bne(cd, iptr->dst.block);
break;
case ICMD_IFGT:
- M_BGT(0);
+ emit_bgt(cd, iptr->dst.block);
break;
case ICMD_IFGE:
- M_BGE(0);
+ emit_bge(cd, iptr->dst.block);
break;
case ICMD_IFEQ:
- M_BEQ(0);
+ emit_beq(cd, iptr->dst.block);
break;
}
- codegen_add_branch_ref(cd, iptr->dst.block);
-
- break;
- case ICMD_IF_LEQ: /* ..., value ==> ... */
- OOPS();
-#if 0
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- if (IS_IMM32(iptr->sx.val.l))
- M_LCMP_IMM(iptr->sx.val.l, s1);
- else {
- M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
- M_LCMP(REG_ITMP2, s1);
- }
- M_BEQ(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
-#endif
break;
case ICMD_IF_LLT: /* ..., value ==> ... */
- OOPS();
-#if 0
-
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- if (IS_IMM32(iptr->sx.val.l))
- M_LCMP_IMM(iptr->sx.val.l, s1);
- else {
- M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
- M_LCMP(REG_ITMP2, s1);
- }
- M_BLT(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
-#endif
- break;
-
- case ICMD_IF_LLE: /* ..., value ==> ... */
- OOPS();
-#if 0
-
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- if (IS_IMM32(iptr->sx.val.l))
- M_LCMP_IMM(iptr->sx.val.l, s1);
- else {
- M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
- M_LCMP(REG_ITMP2, s1);
- }
- M_BLE(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
-#endif
- break;
+ case ICMD_IF_LLE: /* op1 = target JavaVM pc, val.l = constant */
+ case ICMD_IF_LGT:
+ case ICMD_IF_LGE:
+ case ICMD_IF_LEQ:
+ case ICMD_IF_LNE:
- case ICMD_IF_LNE: /* ..., value ==> ... */
- OOPS();
-#if 0
+ /* ATTENTION: compare high words signed and low words unsigned */
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- if (IS_IMM32(iptr->sx.val.l))
- M_LCMP_IMM(iptr->sx.val.l, s1);
- else {
- M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
- M_LCMP(REG_ITMP2, s1);
- }
- M_BNE(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
-#endif
- break;
+# define LABEL_OUT BRANCH_LABEL_1
- case ICMD_IF_LGT: /* ..., value ==> ... */
- OOPS();
-#if 0
+ s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- if (IS_IMM32(iptr->sx.val.l))
- M_LCMP_IMM(iptr->sx.val.l, s1);
+ if (N_VALID_IMM(iptr->sx.val.l >> 32))
+ M_ICMP_IMM(s1, iptr->sx.val.l >> 32);
else {
- M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
- M_LCMP(REG_ITMP2, s1);
+ disp = dseg_add_s4(cd, iptr->sx.val.l >> 32);
+ if (N_VALID_DSEG_DISP(disp)) {
+ N_C(s1, N_DSEG_DISP(disp), RN, REG_PV);
+ } else {
+ ICONST(REG_ITMP2, disp);
+ N_C(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
+ }
}
- M_BGT(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
-#endif
- break;
- case ICMD_IF_LGE: /* ..., value ==> ... */
- OOPS();
-#if 0
-
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- if (IS_IMM32(iptr->sx.val.l))
- M_LCMP_IMM(iptr->sx.val.l, s1);
- else {
- M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
- M_LCMP(REG_ITMP2, s1);
+ switch(iptr->opc) {
+ case ICMD_IF_LLT:
+ case ICMD_IF_LLE:
+ emit_blt(cd, iptr->dst.block);
+ /* EQ ... fall through */
+ emit_label_bgt(cd, LABEL_OUT);
+ break;
+ case ICMD_IF_LGT:
+ case ICMD_IF_LGE:
+ emit_bgt(cd, iptr->dst.block);
+ /* EQ ... fall through */
+ emit_label_blt(cd, LABEL_OUT);
+ break;
+ case ICMD_IF_LEQ:
+ /* EQ ... fall through */
+ emit_label_bne(cd, LABEL_OUT);
+ break;
+ case ICMD_IF_LNE:
+ /* EQ ... fall through */
+ emit_bne(cd, iptr->dst.block);
+ break;
+ default:
+ assert(0);
}
- M_BGE(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
-#endif
- break;
-
- case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
- case ICMD_IF_ACMPEQ: /* 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_BEQ(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
- 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 */
- /* TODO do the loads modify the condition code?
- * lr, l, la, lhi dont
- */
- s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
- s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
- M_BNE(SZ_BRC + SZ_CR + SZ_BRC);
- M_CMP(s1, s2);
- M_BEQ(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
- break;
-
- case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
-
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- M_ICMP(s2, s1);
- M_BNE(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
-
- break;
-
- case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
- OOPS();
-#if 0
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- M_LCMP(s2, s1);
- M_BNE(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
-#endif
- break;
+ s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
- case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
- case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
+ disp = dseg_add_s4(cd, (s4)(iptr->sx.val.l & 0xffffffff));
+ if (N_VALID_DSEG_DISP(disp)) {
+ N_CL(s1, N_DSEG_DISP(disp), RN, REG_PV);
+ } else {
+ ICONST(REG_ITMP2, disp);
+ N_CL(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
+ }
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- M_ICMP(s2, s1);
- M_BLT(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
+ switch(iptr->opc) {
+ case ICMD_IF_LLT:
+ emit_blt(cd, iptr->dst.block);
+ emit_label(cd, LABEL_OUT);
+ break;
+ case ICMD_IF_LLE:
+ emit_ble(cd, iptr->dst.block);
+ emit_label(cd, LABEL_OUT);
+ break;
+ case ICMD_IF_LGT:
+ emit_bgt(cd, iptr->dst.block);
+ emit_label(cd, LABEL_OUT);
+ break;
+ case ICMD_IF_LGE:
+ emit_bge(cd, iptr->dst.block);
+ emit_label(cd, LABEL_OUT);
+ break;
+ case ICMD_IF_LEQ:
+ emit_beq(cd, iptr->dst.block);
+ emit_label(cd, LABEL_OUT);
+ break;
+ case ICMD_IF_LNE:
+ emit_bne(cd, iptr->dst.block);
+ break;
+ default:
+ assert(0);
+ }
+# undef LABEL_OUT
break;
- case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
- OOPS();
-#if 0
+ case ICMD_IF_ACMPEQ: /* ..., 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_LCMP(s2, s1);
- M_BLT(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
-#endif
- break;
+ /* Compare addresses as 31 bit unsigned integers */
- case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
+ s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
+ M_LDA(REG_ITMP1, s1, 0);
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- M_ICMP(s2, s1);
- M_BGT(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
+ s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
+ M_LDA(REG_ITMP2, s2, 0);
- break;
+ M_CMP(REG_ITMP1, REG_ITMP2);
- case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
+ switch (iptr->opc) {
+ case ICMD_IF_ACMPEQ:
+ emit_beq(cd, iptr->dst.block);
+ break;
+ case ICMD_IF_ACMPNE:
+ emit_bne(cd, iptr->dst.block);
+ break;
+ }
- OOPS();
-#if 0
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- M_LCMP(s2, s1);
- M_BGT(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
-#endif
break;
+ case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
+ case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
+ case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
+ case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
+ case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- M_ICMP(s2, s1);
- M_BLE(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
+ M_CMP(s1, s2);
+ switch (iptr->opc) {
+ case ICMD_IF_ICMPEQ:
+ emit_beq(cd, iptr->dst.block);
+ break;
+ case ICMD_IF_ICMPNE:
+ emit_bne(cd, iptr->dst.block);
+ break;
+ case ICMD_IF_ICMPLT:
+ emit_blt(cd, iptr->dst.block);
+ break;
+ case ICMD_IF_ICMPGT:
+ emit_bgt(cd, iptr->dst.block);
+ break;
+ case ICMD_IF_ICMPLE:
+ emit_ble(cd, iptr->dst.block);
+ break;
+ case ICMD_IF_ICMPGE:
+ emit_bge(cd, iptr->dst.block);
+ break;
+ }
break;
case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
+ case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
+ case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
+ case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
+ case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
+ 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);
- M_BLT(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
- /* load low-bits before the branch, so we know the distance */
- /* TODO: the loads should not touch the condition code. */
- s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
- s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
- M_BGT(SZ_BRC + SZ_CR + SZ_BRC);
- M_CMP(s1, s2);
- M_BLE(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
- break;
+ u1 *out_ref = NULL;
- case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
+ /* ATTENTION: compare high words signed and low words unsigned */
+
+ s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
+ s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
+
+ M_ICMP(s1, s2);
+
+ switch(iptr->opc) {
+ case ICMD_IF_LCMPLT:
+ case ICMD_IF_LCMPLE:
+ emit_blt(cd, iptr->dst.block);
+ /* EQ ... fall through */
+ out_ref = cd->mcodeptr;
+ M_BGT(0);
+ break;
+ case ICMD_IF_LCMPGT:
+ case ICMD_IF_LCMPGE:
+ emit_bgt(cd, iptr->dst.block);
+ /* EQ ... fall through */
+ out_ref = cd->mcodeptr;
+ M_BLT(0);
+ break;
+ case ICMD_IF_LCMPEQ:
+ /* EQ ... fall through */
+ out_ref = cd->mcodeptr;
+ M_BNE(0);
+ break;
+ case ICMD_IF_LCMPNE:
+ /* EQ ... fall through */
+ emit_bne(cd, iptr->dst.block);
+ break;
+ default:
+ assert(0);
+ }
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- M_ICMP(s2, s1);
- M_BGE(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
+ s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
+ s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
+
+ M_ICMPU(s1, s2);
- break;
+ switch(iptr->opc) {
+ case ICMD_IF_LCMPLT:
+ emit_blt(cd, iptr->dst.block);
+ break;
+ case ICMD_IF_LCMPLE:
+ emit_ble(cd, iptr->dst.block);
+ break;
+ case ICMD_IF_LCMPGT:
+ emit_bgt(cd, iptr->dst.block);
+ break;
+ case ICMD_IF_LCMPGE:
+ emit_bge(cd, iptr->dst.block);
+ break;
+ case ICMD_IF_LCMPEQ:
+ emit_beq(cd, iptr->dst.block);
+ break;
+ case ICMD_IF_LCMPNE:
+ emit_bne(cd, iptr->dst.block);
+ break;
+ default:
+ assert(0);
+ }
- case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
- OOPS();
-#if 0
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- M_LCMP(s2, s1);
- M_BGE(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
-#endif
+ if (out_ref != NULL) {
+ *(u4 *)out_ref |= (u4)(cd->mcodeptr - out_ref) / 2;
+ }
+
+ }
break;
case ICMD_IRETURN: /* ..., retvalue ==> ... */
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
unresolved_class *uc = iptr->sx.s23.s2.uc;
- codegen_addpatchref(cd, PATCHER_athrow_areturn, uc, 0);
+ PROFILE_CYCLE_STOP;
+ patcher_add_patch_ref(jd, PATCHER_athrow_areturn, uc, 0);
+ PROFILE_CYCLE_START;
}
#endif /* ENABLE_VERIFIER */
goto nowperformreturn;
/* call trace function */
- /*emit_verbosecall_exit(jd); TODO */
+#if !defined(NDEBUG)
+ if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
+ emit_verbosecall_exit(jd);
+#endif /* !defined(NDEBUG) */
#if defined(ENABLE_THREADS)
if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
- disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
- M_ALD(REG_ITMP3, REG_PV, disp);
- M_CALL(REG_ITMP3);
-
/* we need to save the proper return value */
switch (iptr->opc) {
case ICMD_LRETURN:
- M_IST(REG_RESULT2, REG_SP, rd->memuse * 4 + 8);
+ M_IST(REG_RESULT2, REG_SP, ((rd->memuse + 1) * 8) + 4);
/* 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 + 1) * 8);
break;
case ICMD_FRETURN:
- M_FST(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
+ M_FST(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
break;
case ICMD_DRETURN:
- M_DST(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
+ M_DST(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
break;
}
- M_ALD(REG_A0, REG_SP, rd->memuse * 4);
- M_JSR;
+ M_ALD(REG_A0, REG_SP, rd->memuse * 8);
+
+ disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
+ M_ALD_DSEG(REG_ITMP3, disp);
+
+ M_ASUB_IMM(96, REG_SP);
+ M_CALL(REG_ITMP3);
+ M_AADD_IMM(96, REG_SP);
/* 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 + 1) * 8) + 4);
/* 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 + 1) * 8);
break;
case ICMD_FRETURN:
- M_FLD(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
+ M_FLD(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
break;
case ICMD_DRETURN:
- M_DLD(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
+ M_DLD(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
break;
}
}
/* restore return address */
- p--; M_ALD(REG_RA, REG_SP, p * 4);
+ p--; M_ALD(REG_RA, REG_SP, p * 8);
/* 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_AADD_IMM(cd->stackframesize * 4, REG_SP);
+ M_AADD_IMM(cd->stackframesize * 8, REG_SP);
+
+ /* generate method profiling code */
+
+ PROFILE_CYCLE_STOP;
M_RET;
- ALIGNCODENOP;
}
break;
case ICMD_TABLESWITCH: /* ..., index ==> ... */
- OOPS();
-#if 0
{
s4 i, l;
branch_target_t *table;
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
M_INTMOVE(s1, REG_ITMP1);
- if (l != 0)
+ if (l == 0) {
+ /* do nothing */
+ } else if (N_VALID_IMM(-l)) {
M_ISUB_IMM(l, REG_ITMP1);
+ } else {
+ ICONST(REG_ITMP2, l);
+ M_ISUB(REG_ITMP2, REG_ITMP1);
+ }
/* number of targets */
+
i = i - l + 1;
- /* range check */
- M_ICMP_IMM(i - 1, REG_ITMP1);
- M_BA(0);
+ /* range check */
- codegen_add_branch_ref(cd, table[0].block); /* default target */
+ ICONST(REG_ITMP2, i);
+ M_ICMPU(REG_ITMP1, REG_ITMP2);
+ emit_bge(cd, table[0].block);
/* build jump table top down and use address of lowest entry */
table += i;
while (--i >= 0) {
- dseg_add_target(cd, table->block);
+ dseg_add_target(cd, table->block);
--table;
}
+ }
- /* length of dataseg after last dseg_add_target is used
- by load */
+ /* length of dataseg after last dseg_add_target is used by load */
+
+ M_SLL_IMM(2, REG_ITMP1); /* scale by 4 */
+ M_ASUB_IMM(cd->dseglen, REG_ITMP1);
+ N_L(REG_ITMP1, -N_PV_OFFSET, REG_ITMP1, REG_PV);
+ M_JMP(RN, REG_ITMP1);
- M_MOV_IMM(0, REG_ITMP2);
- dseg_adddata(cd);
- emit_mov_memindex_reg(cd, -(cd->dseglen), REG_ITMP2, REG_ITMP1, 3, REG_ITMP1);
- M_JMP(REG_ITMP1);
- }
-#endif
break;
case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
- OOPS();
-#if 0
{
s4 i;
lookup_target_t *lookup;
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
while (--i >= 0) {
- M_ICMP_IMM(lookup->value, s1);
- M_BEQ(0);
- codegen_add_branch_ref(cd, lookup->target.block);
+ if (N_VALID_IMM(lookup->value)) {
+ M_ICMP_IMM(s1, lookup->value);
+ } else {
+ ICONST(REG_ITMP2, lookup->value);
+ M_ICMP(REG_ITMP2, s1);
+ }
+ emit_beq(cd, lookup->target.block);
lookup++;
}
- M_JMP_IMM(0);
-
- codegen_add_branch_ref(cd, iptr->sx.s23.s3.lookupdefault.block);
+ emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
}
-#endif
break;
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)]
+ GET_LOW_REG(md->params[s3].regoff),
+ GET_HIGH_REG(md->params[s3].regoff)
);
d = emit_load(jd, iptr, var, s1);
M_LNGMOVE(d, s1);
}
else {
- s1 = rd->argintregs[md->params[s3].regoff];
+ s1 = md->params[s3].regoff;
d = emit_load(jd, iptr, var, s1);
M_INTMOVE(d, s1);
}
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);
+ M_LST(d, REG_SP, md->params[s3].regoff);
}
else {
d = emit_load(jd, iptr, var, REG_ITMP1);
- M_IST(d, REG_SP, md->params[s3].regoff * 4);
+ M_IST(d, REG_SP, md->params[s3].regoff);
}
}
}
else {
if (!md->params[s3].inmemory) {
- s1 = rd->argfltregs[md->params[s3].regoff];
+ s1 = md->params[s3].regoff;
d = emit_load(jd, iptr, var, s1);
M_FLTMOVE(d, s1);
}
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);
+ M_DST(d, REG_SP, md->params[s3].regoff);
else
- M_FST(d, REG_SP, md->params[s3].regoff * 4);
+ M_FST(d, REG_SP, md->params[s3].regoff);
}
}
}
+ /* generate method profiling code */
+
+ PROFILE_CYCLE_STOP;
+
switch (iptr->opc) {
case ICMD_BUILTIN:
disp = dseg_add_functionptr(cd, bte->fp);
- N_LHI(REG_ITMP1, disp);
- N_L(REG_PV, 0, REG_ITMP1, REG_PV);
+ M_ASUB_IMM(96, REG_SP); /* register save area as required by C abi */
+ if (N_VALID_DSEG_DISP(disp)) {
+ N_L(REG_PV, N_DSEG_DISP(disp), RN, REG_PV);
+ } else {
+ N_LHI(REG_ITMP1, disp);
+ N_L(REG_PV, -N_PV_OFFSET, REG_ITMP1, REG_PV);
+ }
break;
case ICMD_INVOKESPECIAL:
- emit_nullpointer_check(cd, iptr, REG_A0);
- M_ILD(REG_ITMP1, REG_A0, 0); /* hardware nullptr */
+ /* TODO softnull */
+ /* Implicit NULL pointer check */
+ M_ILD(REG_ITMP1, REG_A0, 0);
+
/* 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);
- N_LHI(REG_ITMP1, disp);
- N_L(REG_PV, 0, REG_ITMP1, REG_PV);
+ if (N_VALID_DSEG_DISP(disp)) {
+ N_L(REG_PV, N_DSEG_DISP(disp), RN, REG_PV);
+ } else {
+ N_LHI(REG_ITMP1, disp);
+ N_L(REG_PV, -N_PV_OFFSET, REG_ITMP1, REG_PV);
+ }
break;
case ICMD_INVOKEVIRTUAL:
- emit_nullpointer_check(cd, iptr, REG_A0);
+ /* TODO softnull 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);
break;
case ICMD_INVOKEINTERFACE:
- emit_nullpointer_check(cd, iptr, REG_A0);
+ /* TODO softnull REG_A0 */
+
+ /* s1 will be negative here, so use (0xFFF + s1) as displacement
+ * and -0xFFF in index register (itmp1)
+ */
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));
- M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
+ /* Implicit null-pointer check */
+ M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
+ N_LHI(REG_ITMP1, s1);
+ N_L(REG_METHODPTR, 0, REG_ITMP1, REG_METHODPTR);
M_ALD(REG_PV, REG_METHODPTR, s2);
break;
}
/* generate the actual call */
M_CALL(REG_PV);
- REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
- N_BASR(REG_ITMP1, RN);
- disp = (s4) (cd->mcodeptr - cd->mcodebase);
- M_LDA(REG_PV, REG_ITMP1, -disp);
-
- /* actually only used for ICMD_BUILTIN */
+ emit_restore_pv(cd);
+
+ /* post call finalization */
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- M_TEST(REG_RESULT);
- M_BEQ(0);
- codegen_add_fillinstacktrace_ref(cd);
+ switch (iptr->opc) {
+ case ICMD_BUILTIN:
+ M_AADD_IMM(96, REG_SP); /* remove C abi register save area */
+ emit_exception_check(cd, iptr); /* check for exception */
+ break;
}
+ /* generate method profiling code */
+
+ PROFILE_CYCLE_START;
+
+ /* store size of call code in replacement point */
+
+ REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
+
/* store return value */
d = md->returntype.type;
vftbl_t *supervftbl;
s4 superindex;
- u1 *class_label_refs[] = { 0 }, *class_label;
- u1 *exit_label_refs[] = { 0, 0, 0, 0 };
+# define LABEL_EXIT_CHECK_NULL BRANCH_LABEL_1
+# define LABEL_CLASS BRANCH_LABEL_2
+# define LABEL_EXIT_INTERFACE_NULL BRANCH_LABEL_3
+# define LABEL_EXIT_INTERFACE_DONE BRANCH_LABEL_4
+# define LABEL_EXIT_CLASS_NULL BRANCH_LABEL_5
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
super = NULL;
supervftbl = super->vftbl;
}
-#if defined(ENABLE_THREADS)
- codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
-#endif
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+ if ((super == NULL) || !(super->flags & ACC_INTERFACE))
+ CODEGEN_CRITICAL_SECTION_NEW;
+
+ s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
/* if class is not resolved, check which code to call */
if (super == NULL) {
M_TEST(s1);
- exit_label_refs[0] = cd->mcodeptr;
- M_BEQ(0);
+ emit_label_beq(cd, LABEL_EXIT_CHECK_NULL);
disp = dseg_add_unique_s4(cd, 0); /* super->flags */
- codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_flags,
+ patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
iptr->sx.s23.s3.c.ref,
disp);
ICONST(REG_ITMP2, ACC_INTERFACE);
- ICONST(REG_ITMP3, disp); /* TODO negative displacement */
- N_N(REG_ITMP2, 0, REG_ITMP3, REG_PV);
- class_label_refs[0] = cd->mcodeptr;
- M_BEQ(0);
+ if (N_VALID_DSEG_DISP(disp)) {
+ N_N(REG_ITMP2, N_DSEG_DISP(disp), RN, REG_PV);
+ } else {
+ ICONST(REG_ITMP3, disp);
+ N_N(REG_ITMP2, -N_PV_OFFSET, REG_ITMP3, REG_PV);
+ }
+ emit_label_beq(cd, LABEL_CLASS);
}
/* interface checkcast code */
if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
if (super == NULL) {
- codegen_add_patch_ref(cd,
+ patcher_add_patch_ref(jd,
PATCHER_checkcast_instanceof_interface,
iptr->sx.s23.s3.c.ref,
0);
} else {
M_TEST(s1);
- exit_label_refs[1] = cd->mcodeptr;
- M_BEQ(0);
+ emit_label_beq(cd, LABEL_EXIT_INTERFACE_NULL);
}
- 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_TEST(REG_ITMP3);
- M_BLE(0);
- codegen_add_classcastexception_ref(cd, s1);
- M_ALD(REG_ITMP3, REG_ITMP2,
- (s4) (OFFSET(vftbl_t, interfacetable[0]) -
- superindex * sizeof(methodptr*)));
- M_TEST(REG_ITMP3);
- M_BEQ(0);
- codegen_add_classcastexception_ref(cd, s1);
+ M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
+ M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
+ M_ISUB_IMM(superindex, REG_ITMP3);
+ emit_classcast_check(cd, iptr, BRANCH_LE, RN, s1);
+ N_AHI(
+ REG_ITMP2,
+ (s4) (OFFSET(vftbl_t, interfacetable[0]) -
+ superindex * sizeof(methodptr*))
+ );
+ M_ALD(REG_ITMP2, REG_ITMP2, 0);
+ emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ITMP2, s1);
if (super == NULL) {
- exit_label_refs[2] = cd->mcodeptr;
- M_BR(0);
+ emit_label_br(cd, LABEL_EXIT_INTERFACE_DONE);
}
}
/* class checkcast code */
-
- class_label = cd->mcodeptr;
+
+ if (super == NULL) {
+ emit_label(cd, LABEL_CLASS);
+ }
if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
if (super == NULL) {
disp = dseg_add_unique_address(cd, NULL);
- codegen_add_patch_ref(cd,
+ patcher_add_patch_ref(jd,
PATCHER_resolve_classref_to_vftbl,
iptr->sx.s23.s3.c.ref,
disp);
else {
disp = dseg_add_address(cd, supervftbl);
M_TEST(s1);
- exit_label_refs[3] = cd->mcodeptr;
- M_BEQ(0);
+ emit_label_beq(cd, LABEL_EXIT_CLASS_NULL);
}
- M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
- M_ALD(REG_ITMP3, REG_PV, disp);
-#if defined(ENABLE_THREADS)
- codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
-#endif
+ M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
+ M_ALD_DSEG(REG_ITMP3, disp);
+
+ 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_ISUB(REG_ITMP2, REG_ITMP3);
- M_ALD(REG_ITMP3, REG_PV, disp);
+ M_ISUB(REG_ITMP3, REG_ITMP2);
+ M_ALD_DSEG(REG_ITMP3, disp);
M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
-#if defined(ENABLE_THREADS)
- codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
-#endif
- /* } */
- N_CLR(REG_ITMP2, REG_ITMP3); /* Unsigned compare */
+
+ CODEGEN_CRITICAL_SECTION_END;
+
+ M_CMPU(REG_ITMP2, REG_ITMP3); /* Unsigned compare */
/* M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3); itmp3 = (itmp2 <= itmp3) */
- M_BGT(0); /* Branch if greater then */
/* M_BEQZ(REG_ITMP3, 0); branch if (! itmp) -> branch if > */
- codegen_add_classcastexception_ref(cd, s1);
+ /* Branch if greater then */
+ emit_classcast_check(cd, iptr, BRANCH_GT, RN, s1);
}
- /* resolve labels by adding the correct displacement */
-
- for (s2 = 0; s2 < sizeof(exit_label_refs) / sizeof(exit_label_refs[0]); ++s2) {
- if (exit_label_refs[s2])
- *(u4 *)exit_label_refs[s2] |= (u4)(cd->mcodeptr - exit_label_refs[s2]) / 2;
- }
-
- for (s2 = 0; s2 < sizeof(class_label_refs) / sizeof(class_label_refs[0]); ++s2) {
- if (class_label_refs[s2])
- *(u4 *)class_label_refs[s2] |= (u4)(class_label - class_label_refs[s2]) / 2;
+ if (super == NULL) {
+ emit_label(cd, LABEL_EXIT_CHECK_NULL);
+ emit_label(cd, LABEL_EXIT_INTERFACE_DONE);
+ } else if (super->flags & ACC_INTERFACE) {
+ emit_label(cd, LABEL_EXIT_INTERFACE_NULL);
+ } else {
+ emit_label(cd, LABEL_EXIT_CLASS_NULL);
}
d = codegen_reg_of_dst(jd, iptr, s1);
+
+# undef LABEL_EXIT_CHECK_NULL
+# undef LABEL_CLASS
+# undef LABEL_EXIT_INTERFACE_NULL
+# undef LABEL_EXIT_INTERFACE_DONE
+# undef LABEL_EXIT_CLASS_NULL
}
else {
/* array type cast-check */
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
disp = dseg_add_unique_address(cd, NULL);
- codegen_add_patch_ref(cd,
+ patcher_add_patch_ref(jd,
PATCHER_resolve_classref_to_classinfo,
iptr->sx.s23.s3.c.ref,
disp);
else
disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
- M_ALD(REG_A1, REG_PV, disp);
+ M_ALD_DSEG(REG_A1, disp);
disp = dseg_add_functionptr(cd, BUILTIN_arraycheckcast);
- ICONST(REG_ITMP1, disp); /* TODO negative displacement */
- N_L(REG_PV, 0, REG_ITMP1, REG_PV);
- M_JSR(REG_RA, REG_PV);
- N_BASR(REG_ITMP1, RN);
- disp = (s4) (cd->mcodeptr - cd->mcodebase);
- M_LDA(REG_PV, REG_ITMP1, -disp);
+ M_ALD_DSEG(REG_ITMP1, disp);
+ M_ASUB_IMM(96, REG_SP);
+ M_JSR(REG_RA, REG_ITMP1);
+ M_AADD_IMM(96, REG_SP);
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- M_TEST(REG_RESULT);
- M_BEQ(0);
- codegen_add_classcastexception_ref(cd, s1);
+ emit_classcast_check(cd, iptr, BRANCH_EQ, REG_RESULT, s1);
d = codegen_reg_of_dst(jd, iptr, s1);
}
break;
case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
- OOPS();
-#if 0
/* val.a: (classinfo*) superclass */
/* superclass is an interface:
* return ((sub != NULL) && (0
* <= (sub->vftbl->baseval - super->vftbl->baseval) <=
* super->vftbl->diffvall));
+ *
+ * If superclass is unresolved, we include both code snippets
+ * above, a patcher resolves the class' flags and we select
+ * the right code at runtime.
*/
{
supervftbl = super->vftbl;
}
-#if defined(ENABLE_THREADS)
- codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
-#endif
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+# define LABEL_EXIT_CHECK_NULL BRANCH_LABEL_1
+# define LABEL_CLASS BRANCH_LABEL_2
+# define LABEL_EXIT_INTERFACE_NULL BRANCH_LABEL_3
+# define LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE BRANCH_LABEL_4
+# define LABEL_EXIT_INTERFACE_DONE BRANCH_LABEL_5
+# define LABEL_EXIT_CLASS_NULL BRANCH_LABEL_6
+
+ if ((super == NULL) || !(super->flags & ACC_INTERFACE))
+ CODEGEN_CRITICAL_SECTION_NEW;
+
+ s1 = emit_load_s1_notzero(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 = 6;
- if (super == NULL)
- s2 += (d == REG_ITMP2 ? 1 : 0) + (opt_shownops ? 1 : 0);
-
- /* calculate class instanceof code size */
-
- s3 = 7;
- if (super == NULL)
- s3 += (opt_shownops ? 1 : 0);
-
/* if class is not resolved, check which code to call */
if (super == NULL) {
M_CLR(d);
- M_BEQZ(s1, 4 + (opt_shownops ? 1 : 0) + s2 + 1 + s3);
+
+ M_TEST(s1);
+ emit_label_beq(cd, LABEL_EXIT_CHECK_NULL);
disp = dseg_add_unique_s4(cd, 0); /* super->flags */
- codegen_add_patch_ref(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);
+ ICONST(REG_ITMP2, ACC_INTERFACE);
+
+ if (N_VALID_DSEG_DISP(disp)) {
+ N_N(REG_ITMP2, N_DSEG_DISP(disp), RN, REG_PV);
+ } else {
+ ICONST(REG_ITMP3, disp);
+ N_N(REG_ITMP2, -N_PV_OFFSET, REG_ITMP3, REG_PV);
+ }
- disp = dseg_add_s4(cd, ACC_INTERFACE);
- M_ILD(REG_ITMP2, REG_PV, disp);
- M_AND(REG_ITMP3, REG_ITMP2, REG_ITMP3);
- M_BEQZ(REG_ITMP3, s2 + 1);
+ emit_label_beq(cd, LABEL_CLASS);
}
/* interface instanceof code */
if (d == REG_ITMP2)
M_CLR(d);
- codegen_add_patch_ref(cd,
+ patcher_add_patch_ref(jd,
PATCHER_checkcast_instanceof_interface,
iptr->sx.s23.s3.c.ref, 0);
}
else {
M_CLR(d);
- M_BEQZ(s1, s2);
+ M_TEST(s1);
+ emit_label_beq(cd, LABEL_EXIT_INTERFACE_NULL);
}
- 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_LDA(REG_ITMP3, REG_ITMP3, -superindex);
- M_BLEZ(REG_ITMP3, 2);
- M_ALD(REG_ITMP1, REG_ITMP1,
- (s4) (OFFSET(vftbl_t, interfacetable[0]) -
- superindex * sizeof(methodptr*)));
- M_CMPULT(REG_ZERO, REG_ITMP1, d); /* REG_ITMP1 != 0 */
+ M_ISUB_IMM(superindex, REG_ITMP3);
+
+ emit_label_ble(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
+
+ N_AHI(
+ REG_ITMP1,
+ (s4) (OFFSET(vftbl_t, interfacetable[0]) -
+ superindex * sizeof(methodptr*))
+ );
+ M_ALD(REG_ITMP1, REG_ITMP1, 0);
+
+ /* d := (REG_ITMP1 != 0) */
- if (super == NULL)
- M_BR(s3);
+ N_LTR(d, REG_ITMP1);
+ M_BEQ(SZ_BRC + SZ_LHI);
+ N_LHI(d, 1);
+
+ if (super == NULL) {
+ emit_label_br(cd, LABEL_EXIT_INTERFACE_DONE);
+ }
}
/* class instanceof code */
+ if (super == NULL) {
+ emit_label(cd, LABEL_CLASS);
+ }
+
if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
if (super == NULL) {
disp = dseg_add_unique_address(cd, NULL);
- codegen_add_patch_ref(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, supervftbl);
M_CLR(d);
- M_BEQZ(s1, s3);
+
+ M_TEST(s1);
+ emit_label_beq(cd, LABEL_EXIT_CLASS_NULL);
}
- M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
- M_ALD(REG_ITMP2, REG_PV, disp);
-#if defined(ENABLE_THREADS)
- codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
-#endif
+ M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
+ M_ALD_DSEG(REG_ITMP2, 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));
-#if defined(ENABLE_THREADS)
- codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
-#endif
- M_ISUB(REG_ITMP1, REG_ITMP3);
- N_CLR(REG_ITMP1, REG_ITMP2);
- M_CMPULE(REG_ITMP1, REG_ITMP2, d);
+
+ CODEGEN_CRITICAL_SECTION_END;
+
+ M_ISUB(REG_ITMP3, REG_ITMP1); /* itmp1 := itmp1 (sub.baseval) - itmp3 (super.baseval) */
+
+ M_CMPU(REG_ITMP1, REG_ITMP2); /* d := (uint)REG_ITMP1 <= (uint)REG_ITMP2 */
+ N_LHI(d, 0);
+ M_BGT(SZ_BRC + SZ_LHI);
+ N_LHI(d, 1);
+ }
+
+ if (super == NULL) {
+ emit_label(cd, LABEL_EXIT_CHECK_NULL);
+ emit_label(cd, LABEL_EXIT_INTERFACE_DONE);
+ emit_label(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
+ } else if (super->flags & ACC_INTERFACE) {
+ emit_label(cd, LABEL_EXIT_INTERFACE_NULL);
+ emit_label(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
+ } else {
+ emit_label(cd, LABEL_EXIT_CLASS_NULL);
}
+
+# undef LABEL_EXIT_CHECK_NULL
+# undef LABEL_CLASS
+# undef LABEL_EXIT_INTERFACE_NULL
+# undef LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE
+# undef LABEL_EXIT_INTERFACE_DONE
+# undef LABEL_EXIT_CLASS_NULL
+
emit_store_dst(jd, iptr, d);
+
}
-#endif
+
break;
case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
- OOPS();
-#if 0
/* check for negative sizes and copy sizes to stack if necessary */
- MCODECHECK((10 * 4 * iptr->s1.argcount) + 5 + 10 * 8);
+ /*MCODECHECK((10 * 4 * iptr->s1.argcount) + 5 + 10 * 8);*/
+ MCODECHECK(512);
for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
/* Already Preallocated? */
if (!(var->flags & PREALLOC)) {
s2 = emit_load(jd, iptr, var, REG_ITMP1);
- M_LST(s2, REG_SP, s1 * 8);
+ M_IST(s2, REG_SP, s1 * 4);
}
}
/* is a patcher function set? */
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
- codegen_add_patch_ref(cd, PATCHER_builtin_multianewarray,
- iptr->sx.s23.s3.c.ref, 0);
+ disp = dseg_add_unique_address(cd, 0);
+
+ patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
+ iptr->sx.s23.s3.c.ref,
+ disp);
}
+ else
+ disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
/* a0 = dimension count */
- M_MOV_IMM(iptr->s1.argcount, REG_A0);
+ ICONST(REG_A0, iptr->s1.argcount);
/* a1 = classinfo */
- M_MOV_IMM(iptr->sx.s23.s3.c.cls, REG_A1);
+ M_ALD_DSEG(REG_A1, disp);
/* a2 = pointer to dimensions = stack pointer */
M_MOV(REG_SP, REG_A2);
- M_MOV_IMM(BUILTIN_multianewarray, REG_ITMP1);
- M_CALL(REG_ITMP1);
+ disp = dseg_add_functionptr(cd, BUILTIN_multianewarray);
+ M_ALD_DSEG(REG_ITMP1, disp);
+ M_ASUB_IMM(96, REG_SP);
+ M_JSR(REG_RA, REG_ITMP1);
+ M_AADD_IMM(96, REG_SP);
/* check for exception before result assignment */
- M_TEST(REG_RESULT);
- M_BEQ(0);
- codegen_add_fillinstacktrace_ref(cd);
+ emit_exception_check(cd, iptr);
s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
M_INTMOVE(REG_RESULT, s1);
emit_store_dst(jd, iptr, s1);
-#endif
+
break;
default:
/* generate stubs */
- emit_exception_stubs(jd);
- emit_patcher_stubs(jd);
-#if 0
- emit_replacement_stubs(jd);
-#endif
-
- 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 (SZ_AHI + SZ_L + SZ_L + SZ_BR)
-
-#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;
- codeinfo *code;
+ 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;
-
- /* Store the codeinfo pointer in the same place as in the
- methodheader for compiled methods. */
- code = code_codeinfo_new(m);
+ /* get required compiler data */
- d[0] = (ptrint) asm_call_jit_compiler;
- d[1] = (ptrint) m;
- d[2] = (ptrint) code;
+ m = jd->m;
+ cd = jd->cd;
/* code for the stub */
/* don't touch ITMP3 as it cointains the return address */
- M_ISUB_IMM((3 * 4), REG_PV); /* suppress negative displacements */
+ M_AADD_IMM(N_PV_OFFSET, REG_PV); /* suppress negative displacements */
- M_ILD(REG_ITMP1, REG_PV, 1 * 4); /* methodinfo */
+ M_ILD_DSEG(REG_ITMP1, -2 * SIZEOF_VOID_P); /* methodinfo */
/* TODO where is methodpointer loaded into itmp2? is it already inside? */
- M_ILD(REG_PV, REG_PV, 0 * 4); /* compiler pointer */
+ M_ILD_DSEG(REG_PV, -3 * SIZEOF_VOID_P); /* compiler pointer */
N_BR(REG_PV);
-
-#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.
*******************************************************************************/
SP after method entry
*/
-u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
+void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
{
methodinfo *m;
codeinfo *code;
nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
/* calculate stack frame size */
-#if 0
- cd->stackframesize =
- sizeof(stackframeinfo) / SIZEOF_VOID_P +
- sizeof(localref_table) / SIZEOF_VOID_P +
- INT_ARG_CNT + FLT_ARG_CNT +
- 1 + /* functionptr, TODO: store in data segment */
- nmd->memuse;
-
- cd->stackframesize |= 0x1; /* keep stack 16-byte aligned */
-#endif
cd->stackframesize =
1 + /* r14 - return address */ +
- sizeof(stackframeinfo) / SIZEOF_VOID_P +
- sizeof(localref_table) / SIZEOF_VOID_P +
+ ((sizeof(stackframeinfo) + 7) / 8) +
+ ((sizeof(localref_table) + 7) / 8) +
1 + /* itmp3 */
- (INT_ARG_CNT + FLT_ARG_CNT) * 2 +
+ (INT_ARG_CNT + FLT_ARG_CNT) +
nmd->memuse + /* parameter passing */
- 96 / SIZEOF_VOID_P /* required by ABI */;
-
+ (96 / 8) /* required by ABI */;
/* create method header */
(void) dseg_addlinenumbertablesize(cd);
(void) dseg_add_unique_s4(cd, 0); /* ExTableSize */
+ /* generate stub code */
+
+ N_AHI(REG_SP, -(cd->stackframesize * 8));
+ N_AHI(REG_PV, N_PV_OFFSET);
+
/* generate native method profiling code */
-#if 0
+
+#if defined(ENABLE_PROFILING)
if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
/* count frequency */
-
- M_MOV_IMM(code, REG_ITMP3);
- M_IINC_MEMBASE(REG_ITMP3, OFFSET(codeinfo, frequency));
+ M_ALD_DSEG(REG_ITMP1, CodeinfoPointer);
+ ICONST(REG_ITMP2, 1);
+ N_AL(REG_ITMP2, OFFSET(codeinfo, frequency), RN, REG_ITMP1);
+ M_IST(REG_ITMP2, REG_ITMP1, OFFSET(codeinfo, frequency));
}
#endif
- /* generate stub code */
-
- N_AHI(REG_SP, -(cd->stackframesize * SIZEOF_VOID_P));
-
/* save return address */
- N_ST(R14, (cd->stackframesize - 1) * SIZEOF_VOID_P, RN, REG_SP);
+ N_ST(R14, (cd->stackframesize - 1) * 8, RN, REG_SP);
-#if 0
#if !defined(NDEBUG)
if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
emit_verbosecall_enter(jd);
-#endif
#endif
/* get function address (this must happen before the stackframeinfo) */
+ disp = dseg_add_functionptr(cd, f);
+
#if !defined(WITH_STATIC_CLASSPATH)
if (f == NULL)
- codegen_add_patch_ref(cd, PATCHER_resolve_native, m, 0);
+ patcher_add_patch_ref(jd, PATCHER_resolve_native_function, m, disp);
#endif
- disp = dseg_add_functionptr(cd, f);
- M_ILD(REG_ITMP1, REG_PV, disp);
+ M_ILD_DSEG(REG_ITMP1, disp);
- j = 96 + (nmd->memuse * 4);
+ j = 96 + (nmd->memuse * 8);
/* todo some arg registers are not volatile in C-abi terms */
for (i = 0; i < md->paramcount; i++) {
if (! md->params[i].inmemory) {
s1 = md->params[i].regoff;
+ t = md->paramtypes[i].type;
- if (IS_INT_LNG_TYPE(md->paramtypes[i].type)) {
+ if (IS_INT_LNG_TYPE(t)) {
if (IS_2_WORD_TYPE(t)) {
/* todo store multiple */
- N_ST(rd->argintregs[GET_HIGH_REG(s1)], j, RN, REG_SP);
- N_ST(rd->argintregs[GET_LOW_REG(s1)], j + 4, RN, REG_SP);
+ N_ST(GET_HIGH_REG(s1), j, RN, REG_SP);
+ N_ST(GET_LOW_REG(s1), j + 4, RN, REG_SP);
} else {
- N_ST(rd->argintregs[s1], j, RN, REG_SP);
+ N_ST(s1, j, RN, REG_SP);
}
} else {
if (IS_2_WORD_TYPE(t)) {
- N_STD(rd->argfltregs[s1], j, RN, REG_SP);
+ N_STD(s1, j, RN, REG_SP);
} else {
- N_STE(rd->argfltregs[s1], j, RN, REG_SP);
+ N_STE(s1, j, RN, REG_SP);
}
}
/* create dynamic stack info */
- N_LAE(REG_A0, (cd->stackframesize - 1) * 4, RN, REG_SP); /* datasp */
- N_LR(REG_A1, REG_PV); /* pv */
- N_LAE(REG_A2, cd->stackframesize * 4, RN, REG_SP); /* old SP */
- N_L(REG_A3, (cd->stackframesize - 1) * 4, RN, REG_SP); /* return address */
+ N_LAE(REG_A0, (cd->stackframesize - 1) * 8 , RN, REG_SP); /* datasp */
+ N_LA(REG_A1, -N_PV_OFFSET, RN, REG_PV); /* pv */
+ N_LAE(REG_A2, cd->stackframesize * 8, RN, REG_SP); /* old SP */
+ N_L(REG_A3, (cd->stackframesize - 1) * 8, RN, REG_SP); /* return address */
disp = dseg_add_functionptr(cd, codegen_start_native_call);
- M_ILD(REG_ITMP1, REG_PV, disp);
+ M_ILD_DSEG(REG_ITMP1, disp);
M_CALL(REG_ITMP1); /* call */
/* restore integer and float argument registers */
- j = 96 + (nmd->memuse * 4);
+ j = 96 + (nmd->memuse * 8);
for (i = 0; i < md->paramcount; i++) {
if (! md->params[i].inmemory) {
s1 = md->params[i].regoff;
+ t = md->paramtypes[i].type;
- if (IS_INT_LNG_TYPE(md->paramtypes[i].type)) {
+ if (IS_INT_LNG_TYPE(t)) {
if (IS_2_WORD_TYPE(t)) {
/* todo load multiple ! */
- N_L(rd->argintregs[GET_HIGH_REG(s1)], j, RN, REG_SP);
- N_L(rd->argintregs[GET_LOW_REG(s1)], j + 4, RN, REG_SP);
+ N_L(GET_HIGH_REG(s1), j, RN, REG_SP);
+ N_L(GET_LOW_REG(s1), j + 4, RN, REG_SP);
} else {
- N_L(rd->argintregs[s1], j, RN, REG_SP);
+ N_L(s1, j, RN, REG_SP);
}
} else {
if (IS_2_WORD_TYPE(t)) {
- N_LD(rd->argfltregs[s1], j, RN, REG_SP);
+ N_LD(s1, j, RN, REG_SP);
} else {
- N_LE(rd->argfltregs[s1], j, RN, REG_SP);
+ N_LE(s1, j, RN, REG_SP);
}
}
if (!md->params[i].inmemory) {
- s1 = rd->argintregs[md->params[i].regoff];
+ s1 = md->params[i].regoff;
if (!nmd->params[j].inmemory) {
- s2 = rd->argintregs[nmd->params[j].regoff];
+ s2 = nmd->params[j].regoff;
if (IS_2_WORD_TYPE(t)) {
- N_LR(GET_HIGH_REG(s2), GET_HIGH_REG(s1));
- N_LR(GET_LOW_REG(s2), GET_LOW_REG(s1));
+ N_LR(
+ GET_LOW_REG(s2),
+ GET_LOW_REG(s1)
+ );
+ N_LR(
+ GET_HIGH_REG(s2),
+ GET_HIGH_REG(s1)
+ );
} else {
- N_LR(s2, s1);
+ N_LR(
+ s2,
+ s1
+ );
}
} else {
s2 = nmd->params[j].regoff;
if (IS_2_WORD_TYPE(t)) {
- N_LM(GET_LOW_REG(s1), GET_HIGH_REG(s1), 96 + (s2 * 4), REG_SP);
+ N_STM(
+ GET_HIGH_REG(s1),
+ GET_LOW_REG(s1),
+ 96 + s2, REG_SP
+ );
} else {
- N_L(s1, 96 + (s2 * 4), RN, REG_SP);
+ N_ST(
+ s1,
+ 96 + s2, RN, REG_SP
+ );
}
}
} else {
- s1 = md->params[i].regoff + cd->stackframesize + 1; /* + 1 (RA) */
+ s1 = cd->stackframesize * 8 + md->params[i].regoff;
s2 = nmd->params[j].regoff;
if (IS_2_WORD_TYPE(t)) {
- N_MVC(96 + (s2 * 4), 8, REG_SP, s1, REG_SP);
+ N_MVC(96 + s2, 8, REG_SP, s1, REG_SP);
} else {
- N_MVC(96 + (s2 * 4), 4, REG_SP, s1, REG_SP);
+ N_MVC(96 + s2, 4, REG_SP, s1, REG_SP);
}
}
/* registers keep unchanged. */
if (md->params[i].inmemory) {
- s1 = md->params[i].regoff + cd->stackframesize + 1; /* + 1 (RA) */
+ s1 = cd->stackframesize * 8 + md->params[i].regoff;
s2 = nmd->params[j].regoff;
if (IS_2_WORD_TYPE(t)) {
- N_MVC(96 + (s2 * 4), 8, REG_SP, s1, REG_SP);
+ N_MVC(96 + s2, 8, REG_SP, s1, REG_SP);
} else {
- N_MVC(96 + (s2 * 4), 4, REG_SP, s1, REG_SP);
+ N_MVC(96 + s2, 4, REG_SP, s1, REG_SP);
}
}
}
if (m->flags & ACC_STATIC) {
disp = dseg_add_address(cd, m->class);
- M_ILD(REG_A1, REG_PV, disp);
+ M_ILD_DSEG(REG_A1, disp);
}
/* put env into first argument register */
disp = dseg_add_address(cd, _Jv_env);
- M_ILD(REG_A0, REG_PV, disp);
+ M_ILD_DSEG(REG_A0, disp);
/* do the native function call */
}
}
-#if 0
#if !defined(NDEBUG)
if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
emit_verbosecall_exit(jd);
-#endif
#endif
/* remove native stackframe info */
- N_LAE(REG_A0, cd->stackframesize * 4, RN, REG_SP);
+ N_LAE(REG_A0, (cd->stackframesize - 1) * 8, RN, REG_SP); /* datasp */
disp = dseg_add_functionptr(cd, codegen_finish_native_call);
- M_ILD(REG_ITMP1, REG_PV, disp);
+ M_ALD_DSEG(REG_ITMP1, disp);
M_CALL(REG_ITMP1);
N_LR(REG_ITMP3, REG_RESULT);
}
}
+ /* load return address */
+
+ N_L(REG_ITMP2, (cd->stackframesize - 1) * 8, RN, REG_SP);
+
/* remove stackframe */
- N_AHI(REG_SP, cd->stackframesize * 4);
+ N_AHI(REG_SP, cd->stackframesize * 8);
/* test for exception */
N_LTR(REG_ITMP3, REG_ITMP3);
- N_BRC(DD_NE, SZ_BRC + SZ_BC);
- N_BC(DD_ANY, 0, RN, REG_SP); /* return */
+ N_BRC(DD_NE, SZ_BRC + SZ_BCR);
+
+ /* return */
+
+ N_BCR(DD_ANY, REG_ITMP2);
/* handle exception */
- N_LONG_0();
+ M_MOV(REG_ITMP3, REG_ITMP1_XPTR);
+ M_MOV(REG_ITMP2, REG_ITMP2_XPC); /* get return address from stack */
#if 0
- M_MOV(REG_ITMP3, REG_ITMP1_XPTR);
- M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8); /* get return address from stack */
+ /* TODO */
M_ASUB_IMM(3, REG_ITMP2_XPC); /* callq */
+#endif
- M_MOV_IMM(asm_handle_nat_exception, REG_ITMP3);
- M_JMP(REG_ITMP3);
+ disp = dseg_add_functionptr(cd, asm_handle_nat_exception);
+ M_ALD_DSEG(REG_ITMP3, disp);
+ M_JMP(RN, REG_ITMP3);
/* generate patcher stubs */
- emit_patcher_stubs(jd);
-
-#endif
- codegen_finish(jd);
-
- return code->entrypoint;
- return NULL;
+ emit_patcher_traps(jd);
}
-
+s4 codegen_reg_of_dst_notzero(jitdata *jd, instruction *iptr, s4 tempregnum) {
+ codegendata *cd = jd->cd;
+ s4 reg = codegen_reg_of_dst(jd, iptr, tempregnum);
+ if (reg == 0) {
+ M_MOV(reg, tempregnum);
+ return tempregnum;
+ } else {
+ return reg;
+ }
+}
/*
* These are local overrides for various environment variables in Emacs.