Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- Contact: cacao@cacaojvm.org
-
- Authors: Andreas Krall
- Reinhard Grafl
- Alexander Jordan
- Edwin Steiner
-
$Id: codegen.c 4644 2006-03-16 18:44:46Z edwin $
*/
#include "config.h"
-#include <stdio.h>
#include <assert.h>
-
+#include <stdio.h>
#include "vm/types.h"
#include "vm/builtin.h"
#include "vm/exceptions.h"
#include "vm/global.h"
-#include "vm/loader.h"
-#include "vm/options.h"
-#include "vm/stringlocal.h"
+
#include "vm/jit/asmpart.h"
#include "vm/jit/codegen-common.h"
#include "vm/jit/dseg.h"
#include "vm/jit/emit-common.h"
+#include "vm/jit/sparc64/emit.h"
#include "vm/jit/jit.h"
#include "vm/jit/parse.h"
#include "vm/jit/patcher.h"
#include "vm/jit/reg.h"
+#include "vm/jit/replace.h"
+#include "vm/jit/stacktrace.h"
+#include "vmcore/loader.h"
+#include "vmcore/options.h"
/* XXX use something like this for window control ?
* #define REG_PV (own_window?REG_PV_CALLEE:REG_PV_CALLER)
bool fits_13(s4 disp)
{
- /* printf("fits disp %d?\n", disp); */
+ /*
+ if ((disp < -4096) || (disp > 4095))
+ printf("disp %d\n", disp);
+ */
return (disp >= -4096) && (disp <= 4095);
}
-/* codegen *********************************************************************
+s4 get_lopart_disp(disp)
+{
+ s4 lodisp;
+
+ if (disp > 0)
+ lodisp = setlo_part(disp);
+ else {
+ if (setlo_part(disp) == 0)
+ lodisp = 0;
+ else
+ lodisp = setlo_part(disp) | 0x1c00;
+ }
+
+ return lodisp;
+}
+
+
+/* codegen_emit ****************************************************************
Generates machine code.
*******************************************************************************/
-bool codegen(jitdata *jd)
+bool codegen_emit(jitdata *jd)
{
methodinfo *m;
codeinfo *code;
} else { /* stack arg -> spilled */
/* add the callers window save registers */
- var->vv.regoff = cd->stackframesize + JITSTACK_CNT + s1;
+ var->vv.regoff = cd->stackframesize + s1;
}
}
M_DLD(var->vv.regoff, REG_FP, JITSTACK + (s1 * 8));
} else { /* stack-arg -> spilled */
- var->vv.regoff = cd->stackframesize + JITSTACK_CNT + s1;
+ var->vv.regoff = cd->stackframesize + s1;
}
}
}
break;
case ICMD_INT2CHAR: /* ..., value ==> ..., value */
- case ICMD_INT2SHORT:
+
+ s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+ d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+ M_SLLX_IMM(s1, 48, d);
+ M_SRLX_IMM( d, 48, d);
+ emit_store_dst(jd, iptr, d);
+ break;
+
+ case ICMD_INT2SHORT: /* ..., value ==> ..., value */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
emit_arithmetic_check(cd, iptr, s2);
M_ISEXT(s1, s1);
/* XXX trim s2 like s1 ? */
- M_DIVX(s1, s2, d);
- M_MULX(s2, d, d);
- M_SUB(s1, d, d);
+ M_DIVX(s1, s2, REG_ITMP3);
+ M_MULX(s2, REG_ITMP3, REG_ITMP3);
+ M_SUB(s1, REG_ITMP3, d);
emit_store_dst(jd, iptr, d);
break;
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
emit_arithmetic_check(cd, iptr, s2);
- M_DIVX(s1, s2, d);
- M_MULX(s2, d, d);
- M_SUB(s1, d, d);
+ M_DIVX(s1, s2, REG_ITMP3);
+ M_MULX(s2, REG_ITMP3, REG_ITMP3);
+ M_SUB(s1, REG_ITMP3, d);
emit_store_dst(jd, iptr, d);
break;
break;
case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
- case ICMD_LSHL:
+
+ s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+ s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+ d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+ M_SLL(s1, s2, d);
+ emit_store_dst(jd, iptr, d);
+ break;
+
+ case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
break;
case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
- case ICMD_LSHLCONST: /* val.i = constant */
+ /* val.i = constant */
+
+ s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+ d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
+ M_SLL_IMM(s1, iptr->sx.val.i, d);
+ emit_store_dst(jd, iptr, d);
+ break;
+
+ case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
+ /* val.i = constant */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
emit_store_dst(jd, iptr, d);
break;
- case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
+ case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
/* sx.val.i = constant */
+ /* constant is actually constant - 1 */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
- M_ISEXT(s1, s1); /* trim for 32-bit compare (BGEZ) */
if (s1 == d) {
M_MOV(s1, REG_ITMP1);
s1 = REG_ITMP1;
}
- if ((iptr->sx.val.i >= 0) && (iptr->sx.val.i <= 0xffff)) {
+ M_ISEXT(s1, s1); /* trim for 32-bit compare (BGEZ) */
+ if ((iptr->sx.val.i >= 0) && (iptr->sx.val.i <= 4095)) {
M_AND_IMM(s1, iptr->sx.val.i, d);
- M_BGEZ(s1, 4);
+ M_BGEZ(s1, 5);
M_NOP;
M_SUB(REG_ZERO, s1, d);
M_AND_IMM(d, iptr->sx.val.i, d);
} else {
ICONST(REG_ITMP2, iptr->sx.val.i);
M_AND(s1, REG_ITMP2, d);
- M_BGEZ(s1, 4);
+ M_BGEZ(s1, 5);
M_NOP;
M_SUB(REG_ZERO, s1, d);
M_AND(d, REG_ITMP2, d);
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
disp = dseg_add_float(cd, 0.0);
- M_IST (s1, REG_PV_CALLEE, disp);
- M_FLD (REG_FTMP2, REG_PV_CALLEE, disp); /* REG_FTMP2 needs to be a double temp */
+ M_IST(s1, REG_PV_CALLEE, disp);
+ M_FLD(REG_FTMP2, REG_PV_CALLEE, disp); /* REG_FTMP2 needs to be a double temp */
M_CVTID (REG_FTMP2, d); /* rd gets translated to double target register */
emit_store_dst(jd, iptr, d);
break;
+
+ case ICMD_L2F:
+ s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+ d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
+ disp = dseg_add_double(cd, 0.0);
+ M_STX(s1, REG_PV_CALLEE, disp);
+ M_DLD(REG_FTMP3, REG_PV_CALLEE, disp);
+ M_CVTLF(REG_FTMP3, d);
+ emit_store_dst(jd, iptr, d);
+ break;
+
+ case ICMD_L2D:
+ s1 = emit_load_s1(jd, iptr, REG_ITMP1);
+ d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
+ disp = dseg_add_double(cd, 0.0);
+ M_STX(s1, REG_PV_CALLEE, disp);
+ M_DLD(d, REG_PV_CALLEE, disp);
+ M_CVTLD(d, d);
+ emit_store_dst(jd, iptr, d);
+ break;
case ICMD_F2I: /* ..., value ==> ..., (int) value */
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
s2 = emit_load_s2(jd, iptr, REG_FTMP2);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
M_FCMP(s1,s2);
- M_OR_IMM(REG_ZERO, -1, REG_ITMP3); /* less by default (less or unordered) */
- M_CMOVFEQ_IMM(0, REG_ITMP3); /* 0 if equal */
- M_CMOVFGT_IMM(1, REG_ITMP3); /* 1 if greater */
+ M_OR_IMM(REG_ZERO, -1, d); /* less by default (less or unordered) */
+ M_CMOVFEQ_IMM(0, d); /* 0 if equal */
+ M_CMOVFGT_IMM(1, d); /* 1 if greater */
emit_store_dst(jd, iptr, d);
break;
s2 = emit_load_s2(jd, iptr, REG_FTMP2);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
M_DCMP(s1,s2);
- M_OR_IMM(REG_ZERO, -1, REG_ITMP3); /* less by default (less or unordered) */
- M_CMOVFEQ_IMM(0, REG_ITMP3); /* 0 if equal */
- M_CMOVFGT_IMM(1, REG_ITMP3); /* 1 if greater */
+ M_OR_IMM(REG_ZERO, -1, d); /* less by default (less or unordered) */
+ M_CMOVFEQ_IMM(0, d); /* 0 if equal */
+ M_CMOVFGT_IMM(1, d); /* 1 if greater */
emit_store_dst(jd, iptr, d);
break;
s2 = emit_load_s2(jd, iptr, REG_FTMP2);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
M_FCMP(s1,s2);
- M_OR_IMM(REG_ZERO, 1, REG_ITMP3); /* greater by default (greater or unordered) */
- M_CMOVFEQ_IMM(0, REG_ITMP3); /* 0 if equal */
- M_CMOVFLT_IMM(-1, REG_ITMP3); /* -1 if less */
+ M_OR_IMM(REG_ZERO, 1, d); /* greater by default (greater or unordered) */
+ M_CMOVFEQ_IMM(0, d); /* 0 if equal */
+ M_CMOVFLT_IMM(-1, d); /* -1 if less */
emit_store_dst(jd, iptr, d);
break;
s2 = emit_load_s2(jd, iptr, REG_FTMP2);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
M_DCMP(s1,s2);
- M_OR_IMM(REG_ZERO, 1, REG_ITMP3); /* greater by default (greater or unordered) */
- M_CMOVFEQ_IMM(0, REG_ITMP3); /* 0 if equal */
- M_CMOVFLT_IMM(-1, REG_ITMP3); /* -1 if less */
+ M_OR_IMM(REG_ZERO, 1, d); /* greater by default (greater or unordered) */
+ M_CMOVFEQ_IMM(0, d); /* 0 if equal */
+ M_CMOVFLT_IMM(-1, d); /* -1 if less */
emit_store_dst(jd, iptr, d);
break;
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
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_AADD(s2, s1, REG_ITMP3);
M_BLDS(d, REG_ITMP3, OFFSET(java_bytearray, data[0]));
emit_store_dst(jd, iptr, d);
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
- emit_array_checks(cd, iptr, s1, s2);
+ /* implicit null-pointer check */
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
M_AADD(s2, s1, REG_ITMP3);
M_AADD(s2, REG_ITMP3, REG_ITMP3);
M_SLDU(d, REG_ITMP3, OFFSET(java_chararray, data[0]));
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
- emit_array_checks(cd, iptr, s1, s2);
+ /* implicit null-pointer check */
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
M_AADD(s2, s1, REG_ITMP3);
M_AADD(s2, REG_ITMP3, REG_ITMP3);
M_SLDS(d, REG_ITMP3, OFFSET(java_shortarray, data[0]));
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
- emit_array_checks(cd, iptr, s1, s2);
+ /* implicit null-pointer check */
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
M_ASLL_IMM(s2, 2, REG_ITMP3);
M_AADD(REG_ITMP3, s1, REG_ITMP3);
M_ILD(d, REG_ITMP3, OFFSET(java_intarray, data[0]));
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
- emit_array_checks(cd, iptr, s1, s2);
+ /* implicit null-pointer check */
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
M_ASLL_IMM(s2, 3, REG_ITMP3);
M_AADD(REG_ITMP3, s1, REG_ITMP3);
M_LDX(d, REG_ITMP3, OFFSET(java_longarray, data[0]));
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
- emit_array_checks(cd, iptr, s1, s2);
+ /* implicit null-pointer check */
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
M_ASLL_IMM(s2, 2, REG_ITMP3);
M_AADD(REG_ITMP3, s1, REG_ITMP3);
M_FLD(d, REG_ITMP3, OFFSET(java_floatarray, data[0]));
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
- emit_array_checks(cd, iptr, s1, s2);
+ /* implicit null-pointer check */
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
M_ASLL_IMM(s2, 3, REG_ITMP3);
M_AADD(REG_ITMP3, s1, REG_ITMP3);
M_DLD(d, REG_ITMP3, OFFSET(java_doublearray, data[0]));
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
- emit_array_checks(cd, iptr, s1, s2);
+ /* implicit null-pointer check */
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP3);
M_AADD(REG_ITMP3, s1, REG_ITMP3);
M_ALD(d, REG_ITMP3, OFFSET(java_objectarray, data[0]));
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- emit_array_checks(cd, iptr, s1, s2);
+ /* implicit null-pointer check */
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
M_AADD(s2, s1, REG_ITMP1);
s3 = emit_load_s3(jd, iptr, REG_ITMP3);
M_BST(s3, REG_ITMP1, OFFSET(java_bytearray, data[0]));
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- emit_array_checks(cd, iptr, s1, s2);
+ /* implicit null-pointer check */
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
M_AADD(s2, s1, REG_ITMP1);
M_AADD(s2, REG_ITMP1, REG_ITMP1);
s3 = emit_load_s3(jd, iptr, REG_ITMP3);
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- emit_array_checks(cd, iptr, s1, s2);
+ /* implicit null-pointer check */
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
M_ASLL_IMM(s2, 2, REG_ITMP2);
M_AADD(REG_ITMP2, s1, REG_ITMP1);
s3 = emit_load_s3(jd, iptr, REG_ITMP3);
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- emit_array_checks(cd, iptr, s1, s2);
+ /* implicit null-pointer check */
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
M_ASLL_IMM(s2, 3, REG_ITMP2);
M_AADD(REG_ITMP2, s1, REG_ITMP1);
s3 = emit_load_s3(jd, iptr, REG_ITMP3);
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- emit_array_checks(cd, iptr, s1, s2);
+ /* implicit null-pointer check */
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
M_ASLL_IMM(s2, 2, REG_ITMP2);
M_AADD(REG_ITMP2, s1, REG_ITMP1);
s3 = emit_load_s3(jd, iptr, REG_FTMP1);
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- emit_array_checks(cd, iptr, s1, s2);
+ /* implicit null-pointer check */
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
M_ASLL_IMM(s2, 3, REG_ITMP2);
M_AADD(REG_ITMP2, s1, REG_ITMP1);
s3 = emit_load_s3(jd, iptr, REG_FTMP1);
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- emit_array_checks(cd, iptr, s1, s2);
+ /* implicit null-pointer check */
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
s3 = emit_load_s3(jd, iptr, REG_ITMP3);
M_MOV(s1, rd->argintregs[0]);
M_ALD(REG_ITMP3, REG_PV, disp);
M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
M_NOP;
-
- M_BEQZ(REG_RESULT_CALLER, 0);
- codegen_add_arraystoreexception_ref(cd);
- M_NOP;
+ emit_exception_check(cd, iptr);
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
M_AADD(REG_ITMP2, s1, REG_ITMP1);
s3 = emit_load_s3(jd, iptr, REG_ITMP3);
+ /* implicit null-pointer check */
M_AST_INTERN(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
break;
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- emit_array_checks(cd, iptr, s1, s2);
+ /* implicit null-pointer check */
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
M_AADD(s2, s1, REG_ITMP1);
M_BST(REG_ZERO, REG_ITMP1, OFFSET(java_bytearray, data[0]));
break;
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- emit_array_checks(cd, iptr, s1, s2);
+ /* implicit null-pointer check */
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
M_AADD(s2, s1, REG_ITMP1);
M_AADD(s2, REG_ITMP1, REG_ITMP1);
M_SST(REG_ZERO, REG_ITMP1, OFFSET(java_chararray, data[0]));
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- emit_array_checks(cd, iptr, s1, s2);
+ /* implicit null-pointer check */
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
M_ASLL_IMM(s2, 2, REG_ITMP2);
M_AADD(REG_ITMP2, s1, REG_ITMP1);
M_IST_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_intarray, data[0]));
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- emit_array_checks(cd, iptr, s1, s2);
+ /* implicit null-pointer check */
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
M_ASLL_IMM(s2, 3, REG_ITMP2);
M_AADD(REG_ITMP2, s1, REG_ITMP1);
M_STX_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_longarray, data[0]));
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- emit_array_checks(cd, iptr, s1, s2);
+ /* implicit null-pointer check */
+ emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
M_AADD(REG_ITMP2, s1, REG_ITMP1);
M_AST_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_objectarray, data[0]));
#ifdef ENABLE_VERIFIER
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
- uc = iptr->sx.s23.s2.uc;
+ unresolved_class *uc = iptr->sx.s23.s2.uc;
codegen_add_patch_ref(cd, PATCHER_athrow_areturn, uc, 0);
}
case ICMD_GOTO: /* ... ==> ... */
case ICMD_RET: /* ... ==> ... */
- M_BR(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
- M_NOP;
+ emit_br(cd, iptr->dst.block);
ALIGNCODENOP;
break;
case ICMD_JSR: /* ... ==> ... */
- M_BR(0);
- codegen_add_branch_ref(cd, iptr->sx.s23.s3.jsrtarget.block);
- M_NOP;
+ emit_br(cd, iptr->sx.s23.s3.jsrtarget.block);
ALIGNCODENOP;
break;
case ICMD_IFNULL: /* ..., value ==> ... */
+ case ICMD_IFNONNULL:
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- M_BEQZ(s1, 0);
- codegen_add_branch_ref(cd, iptr->dst.block);
- M_NOP;
- break;
-
- case ICMD_IFNONNULL: /* ..., value ==> ... */
-
- s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- M_BNEZ(s1, 0);
- codegen_add_branch_ref(cd, iptr->dst.block);
- M_NOP;
+ emit_bccz(cd, iptr->dst.block, iptr->opc - ICMD_IFNULL, s1, BRANCH_OPT_NONE);
break;
+
+ /* Note: int compares must not branch on the register directly. */
+ /* Reason is, that register content is not 32-bit clean. */
case ICMD_IFEQ: /* ..., value ==> ... */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- if (iptr->sx.val.i == 0) {
- M_BEQZ(s1, 0);
- } else {
- if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
- M_CMP_IMM(s1, iptr->sx.val.i);
- }
- else {
- ICONST(REG_ITMP2, iptr->sx.val.i);
- M_CMP(s1, REG_ITMP2);
- }
- M_BEQ(0);
- }
- codegen_add_branch_ref(cd, iptr->dst.block);
- M_NOP;
+
+ if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
+ M_CMP_IMM(s1, iptr->sx.val.i);
+ }
+ else {
+ ICONST(REG_ITMP2, iptr->sx.val.i);
+ M_CMP(s1, REG_ITMP2);
+ }
+ emit_beq(cd, iptr->dst.block);
break;
case ICMD_IFLT: /* ..., value ==> ... */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- if (iptr->sx.val.i == 0) {
- M_BLTZ(s1, 0);
- } else {
- if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
- M_CMP_IMM(s1, iptr->sx.val.i);
- } else {
- ICONST(REG_ITMP2, iptr->sx.val.i);
- M_CMP(s1, REG_ITMP2);
- }
- M_BLT(0);
+
+ if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
+ M_CMP_IMM(s1, iptr->sx.val.i);
+ }
+ else {
+ ICONST(REG_ITMP2, iptr->sx.val.i);
+ M_CMP(s1, REG_ITMP2);
}
- codegen_add_branch_ref(cd, iptr->dst.block);
- M_NOP;
+ emit_blt(cd, iptr->dst.block);
break;
case ICMD_IFLE: /* ..., value ==> ... */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- if (iptr->sx.val.i == 0) {
- M_BLEZ(s1, 0);
- }
+
+ if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
+ M_CMP_IMM(s1, iptr->sx.val.i);
+ }
else {
- if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
- M_CMP_IMM(s1, iptr->sx.val.i);
- }
- else {
- ICONST(REG_ITMP2, iptr->sx.val.i);
- M_CMP(s1, REG_ITMP2);
- }
- M_BLE(0);
+ ICONST(REG_ITMP2, iptr->sx.val.i);
+ M_CMP(s1, REG_ITMP2);
}
- codegen_add_branch_ref(cd, iptr->dst.block);
- M_NOP;
+ emit_ble(cd, iptr->dst.block);
break;
case ICMD_IFNE: /* ..., value ==> ... */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- if (iptr->sx.val.i == 0) {
- M_BNEZ(s1, 0);
- }
+
+ if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
+ M_CMP_IMM(s1, iptr->sx.val.i);
+ }
else {
- if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
- M_CMP_IMM(s1, iptr->sx.val.i);
- }
- else {
- ICONST(REG_ITMP2, iptr->sx.val.i);
- M_CMP(s1, REG_ITMP2);
- }
- M_BNE(0);
+ ICONST(REG_ITMP2, iptr->sx.val.i);
+ M_CMP(s1, REG_ITMP2);
}
- codegen_add_branch_ref(cd, iptr->dst.block);
- M_NOP;
+ emit_bne(cd, iptr->dst.block);
break;
case ICMD_IFGT: /* ..., value ==> ... */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- if (iptr->sx.val.i == 0) {
- M_BGTZ(s1, 0);
+
+ if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
+ M_CMP_IMM(s1, iptr->sx.val.i);
}
else {
- if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
- M_CMP_IMM(s1, iptr->sx.val.i);
- } else {
- ICONST(REG_ITMP2, iptr->sx.val.i);
- M_CMP(s1, REG_ITMP2);
- }
- M_BGT(0);
+ ICONST(REG_ITMP2, iptr->sx.val.i);
+ M_CMP(s1, REG_ITMP2);
}
- codegen_add_branch_ref(cd, iptr->dst.block);
- M_NOP;
+ emit_bgt(cd, iptr->dst.block);
break;
case ICMD_IFGE: /* ..., value ==> ... */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- if (iptr->sx.val.i == 0) {
- M_BGEZ(s1, 0);
- }
+
+ if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
+ M_CMP_IMM(s1, iptr->sx.val.i);
+ }
else {
- if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
- M_CMP_IMM(s1, iptr->sx.val.i);
- }
- else {
- ICONST(REG_ITMP2, iptr->sx.val.i);
- M_CMP(s1, REG_ITMP2);
- }
- M_BGE(0);
+ ICONST(REG_ITMP2, iptr->sx.val.i);
+ M_CMP(s1, REG_ITMP2);
}
- codegen_add_branch_ref(cd, iptr->dst.block);
- M_NOP;
+ emit_bge(cd, iptr->dst.block);
break;
case ICMD_IF_LEQ: /* ..., value ==> ... */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- if (iptr->sx.val.l == 0) {
- M_BEQZ(s1, 0);
- }
+ if (iptr->sx.val.l == 0)
+ emit_beqz(cd, iptr->dst.block, s1);
else {
if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
M_CMP_IMM(s1, iptr->sx.val.l);
LCONST(REG_ITMP2, iptr->sx.val.l);
M_CMP(s1, REG_ITMP2);
}
- M_XBEQ(0);
+ emit_beq_xcc(cd, iptr->dst.block);
}
- codegen_add_branch_ref(cd, iptr->dst.block);
- M_NOP;
break;
case ICMD_IF_LLT: /* ..., value ==> ... */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- if (iptr->sx.val.l == 0) {
- M_BLTZ(s1, 0);
- }
+ if (iptr->sx.val.l == 0)
+ emit_bltz(cd, iptr->dst.block, s1);
else {
if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
M_CMP_IMM(s1, iptr->sx.val.l);
}
else {
- ICONST(REG_ITMP2, iptr->sx.val.l);
+ LCONST(REG_ITMP2, iptr->sx.val.l);
M_CMP(s1, REG_ITMP2);
}
- M_XBLT(0);
+ emit_blt_xcc(cd, iptr->dst.block);
}
- codegen_add_branch_ref(cd, iptr->dst.block);
- M_NOP;
break;
case ICMD_IF_LLE: /* ..., value ==> ... */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- if (iptr->sx.val.l == 0) {
- M_BLEZ(s1, 0);
- }
+ if (iptr->sx.val.l == 0)
+ emit_blez(cd, iptr->dst.block, s1);
else {
if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
M_CMP_IMM(s1, iptr->sx.val.l);
- }
+ }
else {
- ICONST(REG_ITMP2, iptr->sx.val.l);
+ LCONST(REG_ITMP2, iptr->sx.val.l);
M_CMP(s1, REG_ITMP2);
}
- M_XBLE(0);
+ emit_ble_xcc(cd, iptr->dst.block);
}
- codegen_add_branch_ref(cd, iptr->dst.block);
- M_NOP;
break;
case ICMD_IF_LNE: /* ..., value ==> ... */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- if (iptr->sx.val.l == 0) {
- M_BNEZ(s1, 0);
- }
+ if (iptr->sx.val.l == 0)
+ emit_bnez(cd, iptr->dst.block, s1);
else {
if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
- M_CMP_IMM(s1, iptr->sx.val.i);
+ M_CMP_IMM(s1, iptr->sx.val.l);
}
else {
- ICONST(REG_ITMP2, iptr->sx.val.l);
+ LCONST(REG_ITMP2, iptr->sx.val.l);
M_CMP(s1, REG_ITMP2);
}
- M_XBNE(0);
+ emit_bne_xcc(cd, iptr->dst.block);
}
- codegen_add_branch_ref(cd, iptr->dst.block);
- M_NOP;
break;
case ICMD_IF_LGT: /* ..., value ==> ... */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- if (iptr->sx.val.l == 0) {
- M_BLTZ(s1, 0);
- } else {
+ if (iptr->sx.val.l == 0)
+ emit_bgtz(cd, iptr->dst.block, s1);
+ else {
if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
M_CMP_IMM(s1, iptr->sx.val.l);
- } else {
- ICONST(REG_ITMP2, iptr->sx.val.l);
+ }
+ else {
+ LCONST(REG_ITMP2, iptr->sx.val.l);
M_CMP(s1, REG_ITMP2);
}
- M_XBGT(0);
+ emit_bgt_xcc(cd, iptr->dst.block);
}
- codegen_add_branch_ref(cd, iptr->dst.block);
- M_NOP;
break;
case ICMD_IF_LGE: /* ..., value ==> ... */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- if (iptr->sx.val.l == 0) {
- M_BLEZ(s1, 0);
- }
+ if (iptr->sx.val.l == 0)
+ emit_bgez(cd, iptr->dst.block, s1);
else {
if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
M_CMP_IMM(s1, iptr->sx.val.l);
- }
+ }
else {
- ICONST(REG_ITMP2, iptr->sx.val.l);
+ LCONST(REG_ITMP2, iptr->sx.val.l);
M_CMP(s1, REG_ITMP2);
}
- M_XBGE(0);
+ emit_bge_xcc(cd, iptr->dst.block);
}
- codegen_add_branch_ref(cd, iptr->dst.block);
- M_NOP;
break;
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
M_CMP(s1, s2);
- M_XBEQ(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
- M_NOP;
+ emit_beq_xcc(cd, iptr->dst.block);
break;
case ICMD_IF_ICMPEQ: /* 32-bit compare */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
M_CMP(s1, s2);
- M_BEQ(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
- M_NOP;
+ emit_beq(cd, iptr->dst.block);
break;
case ICMD_IF_ACMPNE: /* ..., value, value ==> ... */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
M_CMP(s1, s2);
- M_XBNE(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
- M_NOP;
+ emit_bne_xcc(cd, iptr->dst.block);
break;
case ICMD_IF_ICMPNE: /* 32-bit compare */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
M_CMP(s1, s2);
- M_BNE(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
- M_NOP;
+ emit_bne(cd, iptr->dst.block);
break;
case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
M_CMP(s1, s2);
- M_XBLT(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
- M_NOP;
+ emit_blt_xcc(cd, iptr->dst.block);
break;
case ICMD_IF_ICMPLT: /* 32-bit compare */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
M_CMP(s1, s2);
- M_BLT(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
- M_NOP;
+ emit_blt(cd, iptr->dst.block);
break;
case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
M_CMP(s1, s2);
- M_XBGT(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
- M_NOP;
+ emit_bgt_xcc(cd, iptr->dst.block);
break;
case ICMD_IF_ICMPGT: /* 32-bit compare */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
M_CMP(s1, s2);
- M_BGT(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
- M_NOP;
+ emit_bgt(cd, iptr->dst.block);
break;
case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
M_CMP(s1, s2);
- M_BLE(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
- M_NOP;
+ emit_ble_xcc(cd, iptr->dst.block);
break;
case ICMD_IF_ICMPLE: /* 32-bit compare */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
M_CMP(s1, s2);
- M_BLE(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
- M_NOP;
+ emit_ble(cd, iptr->dst.block);
break;
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
M_CMP(s1, s2);
- M_BGE(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
- M_NOP;
+ emit_bge_xcc(cd, iptr->dst.block);
break;
case ICMD_IF_ICMPGE: /* 32-bit compare */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
M_CMP(s1, s2);
- M_BGE(0);
- codegen_add_branch_ref(cd, iptr->dst.block);
- M_NOP;
+ emit_bge(cd, iptr->dst.block);
break;
#ifdef ENABLE_VERIFIER
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
- codegen_addpatchref(cd, PATCHER_athrow_areturn,
- iptr->sx.s23.s2.uc, 0);
+ unresolved_class *uc = iptr->sx.s23.s2.uc;
- if (opt_showdisassemble) {
- M_NOP; M_NOP;
- }
+ codegen_add_patch_ref(cd, PATCHER_athrow_areturn, uc, 0);
}
#endif /* ENABLE_VERIFIER */
goto nowperformreturn;
case ICMD_DRETURN:
s1 = emit_load_s1(jd, iptr, REG_FRESULT);
- M_FLTMOVE(s1, REG_FRESULT);
+ M_DBLMOVE(s1, REG_FRESULT);
goto nowperformreturn;
case ICMD_RETURN: /* ... ==> ... */
/* range check */
if (i <= 4095) {
- M_CMP_IMM(REG_ITMP1, i);
+ M_CMP_IMM(REG_ITMP1, i - 1);
}
else {
- ICONST(REG_ITMP2, i);
+ ICONST(REG_ITMP2, i - 1);
M_CMP(REG_ITMP1, REG_ITMP2);
}
- M_XBULT(0);
- codegen_add_branch_ref(cd, table[0].block); /* default target */
- M_ASLL_IMM(REG_ITMP1, POINTERSHIFT, REG_ITMP1); /* delay slot*/
+ emit_bugt(cd, table[0].block); /* default target */
/* build jump table top down and use address of lowest entry */
/* length of dataseg after last dseg_addtarget is used by load */
+ M_ASLL_IMM(REG_ITMP1, POINTERSHIFT, REG_ITMP1);
M_AADD(REG_ITMP1, REG_PV, REG_ITMP2);
M_ALD(REG_ITMP2, REG_ITMP2, -(cd->dseglen));
M_JMP(REG_ZERO, REG_ITMP2, REG_ZERO);
ICONST(REG_ITMP2, lookup->value);
M_CMP(s1, REG_ITMP2);
}
- M_BEQ(0);
- codegen_add_branch_ref(cd, lookup->target.block);
- M_NOP;
+ emit_beq(cd, lookup->target.block);
++lookup;
}
- M_BR(0);
- codegen_add_branch_ref(cd, iptr->sx.s23.s3.lookupdefault.block);
- M_NOP;
+ emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
ALIGNCODENOP;
break;
}
bte = iptr->sx.s23.s3.bte;
md = bte->md;
- /* XXX: proper builtin calling and float args are so not implemented */
- assert(md->paramcount <= 5 && md->argfltreguse < 1);
+ /* XXX: builtin calling with stack arguments not implemented */
+ assert(md->paramcount <= 5 && md->argfltreguse <= 16);
+
+ s3 = md->paramcount;
+
+ MCODECHECK((s3 << 1) + 64);
+
+ /* copy float arguments according to ABI convention */
+
+ int num_fltregargs = 0;
+ int fltregarg_inswap[16];
+
+ for (s3 = s3 - 1; s3 >= 0; s3--) {
+ var = VAR(iptr->sx.s23.s2.args[s3]);
+
+ if (var->flags & PREALLOC)
+ continue;
+
+ if (IS_FLT_DBL_TYPE(var->type)) {
+ if (!md->params[s3].inmemory) {
+ s1 = md->params[s3].regoff; /*native flt args use regoff directly*/
+ d = emit_load(jd, iptr, var, REG_FTMP1);
+
+ M_DMOV(d, s1 + 16);
+ fltregarg_inswap[num_fltregargs] = s1;
+ num_fltregargs++;
+ /*printf("builtin: flt arg swap to %d\n", s1 + 16);*/
+ }
+ else {
+ assert(0);
+ }
+ }
+ }
+
+ int i;
+ /* move swapped float args to target regs */
+ for (i = 0; i < num_fltregargs; i++) {
+ s1 = fltregarg_inswap[i];
+ M_DMOV(s1 + 16, s1);
+ /*printf("builtin float arg to target reg: %d ==> %d\n", s1+16, s1);*/
+ }
goto gen_method;
}
}
else {
+ if (iptr->opc == ICMD_BUILTIN)
+ continue;
+
if (!md->params[s3].inmemory) {
s1 = rd->argfltregs[md->params[s3].regoff];
d = emit_load(jd, iptr, var, s1);
disp = dseg_add_functionptr(cd, bte->fp);
M_ALD(REG_PV_CALLER, REG_PV, disp); /* built-in-function pointer */
- s1 = REG_PV_CALLER;
/* XXX jit-c-call */
-
+ /* generate the actual call */
+
+ M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
+ M_NOP;
+ disp = (s4) (cd->mcodeptr - cd->mcodebase);
+ /* REG_RA holds the value of the jmp instruction, therefore +8 */
+ M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8);
+
+ emit_exception_check(cd, iptr);
+ if (md->returntype.type == TYPE_FLT) {
+ /* special handling for float return value in %f0 */
+ M_FMOV_INTERN(0,1);
+ }
break;
case ICMD_INVOKESPECIAL:
- M_BEQZ(REG_OUT0, 0);
- codegen_add_nullpointerexception_ref(cd);
- M_NOP;
- /* fall through */
+ emit_nullpointer_check(cd, iptr, REG_OUT0);
+ /* fall-through */
case ICMD_INVOKESTATIC:
if (lm == NULL) {
disp = dseg_add_address(cd, lm->stubroutine);
M_ALD(REG_PV_CALLER, REG_PV, disp); /* method pointer in pv */
- s1 = REG_PV_CALLER;
+
+ /* generate the actual call */
+
+ M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
+ M_NOP;
+ disp = (s4) (cd->mcodeptr - cd->mcodebase);
+ /* REG_RA holds the value of the jmp instruction, therefore +8 */
+ M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8);
break;
case ICMD_INVOKEVIRTUAL:
s1 = OFFSET(vftbl_t, table[0]) +
sizeof(methodptr) * lm->vftblindex;
- M_ALD(REG_METHODPTR, REG_OUT0,
- OFFSET(java_objectheader, vftbl));
+ /* implicit null-pointer check */
+ M_ALD(REG_METHODPTR, REG_OUT0,OFFSET(java_objectheader, vftbl));
M_ALD(REG_PV_CALLER, REG_METHODPTR, s1);
- s1 = REG_PV_CALLER;
+
+ /* generate the actual call */
+
+ M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
+ M_NOP;
+ disp = (s4) (cd->mcodeptr - cd->mcodebase);
+ /* REG_RA holds the value of the jmp instruction, therefore +8 */
+ M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8);
break;
case ICMD_INVOKEINTERFACE:
s2 = sizeof(methodptr) * (lm - lm->class->methods);
}
- M_ALD(REG_METHODPTR, REG_OUT0,
- OFFSET(java_objectheader, vftbl));
+ /* implicit null-pointer check */
+ M_ALD(REG_METHODPTR, REG_OUT0, OFFSET(java_objectheader, vftbl));
M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
M_ALD(REG_PV_CALLER, REG_METHODPTR, s2);
- s1 = REG_PV_CALLER;
- break;
- }
-
- /* generate the actual call */
-
- M_JMP(REG_RA_CALLER, s1, REG_ZERO);
- M_NOP;
- disp = (s4) (cd->mcodeptr - cd->mcodebase);
- /* REG_RA holds the value of the jmp instruction, therefore +8 */
- M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8);
-
- /* actually only used for ICMD_BUILTIN */
-
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- M_BEQZ(REG_RESULT_CALLER, 0);
- codegen_add_fillinstacktrace_ref(cd);
- M_NOP;
+ /* generate the actual call */
+
+ M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
+ M_NOP;
+ disp = (s4) (cd->mcodeptr - cd->mcodebase);
+ /* REG_RA holds the value of the jmp instruction, therefore +8 */
+ M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8);
+ break;
}
/* store return value */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- /* calculate interface checkcast code size */
-
- s2 = 8;
- if (super == NULL)
- s2 += (opt_shownops ? PATCHER_CALL_INSTRUCTIONS : 0);
-
- /* calculate class checkcast code size */
-
- s3 = 10;
- if (super == NULL)
- s3 += (opt_shownops ? PATCHER_CALL_INSTRUCTIONS : 0);
-
/* if class is not resolved, check which code to call */
if (super == NULL) {
- M_BEQZ(s1, 5 + (opt_shownops ? PATCHER_CALL_INSTRUCTIONS : 0) + s2 + 2 + s3 + 1);
- M_NOP;
+ emit_label_beqz(cd, BRANCH_LABEL_1, s1);
cr = iptr->sx.s23.s3.c.ref;
disp = dseg_add_unique_s4(cd, 0); /* super->flags */
M_ILD(REG_ITMP2, REG_PV, disp);
M_AND_IMM(REG_ITMP2, ACC_INTERFACE, REG_ITMP2);
- M_BEQZ(REG_ITMP2, s2 + 2 + 2);
- M_NOP;
+ emit_label_beqz(cd, BRANCH_LABEL_2, REG_ITMP2);
}
/* interface checkcast code */
cr, 0);
}
else {
- M_BEQZ(s1, s2 + 2);
- M_NOP;
+ emit_label_beqz(cd, BRANCH_LABEL_3, s1);
}
M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
M_ILD(REG_ITMP3, REG_ITMP2,
OFFSET(vftbl_t, interfacetablelength));
M_ADD_IMM(REG_ITMP3, -superindex, REG_ITMP3);
- M_BLEZ(REG_ITMP3, 0);
- codegen_add_classcastexception_ref(cd, s1);
- M_NOP;
+ emit_classcast_check(cd, iptr, ICMD_IFLE, REG_ITMP3, s1);
+
M_ALD(REG_ITMP3, REG_ITMP2,
OFFSET(vftbl_t, interfacetable[0]) -
superindex * sizeof(methodptr*));
- M_BEQZ(REG_ITMP3, 0);
- codegen_add_classcastexception_ref(cd, s1);
- M_NOP;
+ emit_classcast_check(cd, iptr, ICMD_IFEQ, REG_ITMP3, s1);
- if (super == NULL) {
- /* on sparc we always add 2 to the size of the code we want */
- /* branch over. (1 for branch delay nop, 1 since the base is */
- /* the address of the branch instruction */
- M_BR(s3 + 2);
- M_NOP;
- }
+ if (super == NULL)
+ emit_label_br(cd, BRANCH_LABEL_4);
+ else
+ emit_label(cd, BRANCH_LABEL_3);
}
/* class checkcast code */
if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
if (super == NULL) {
+ emit_label(cd, BRANCH_LABEL_2);
+
cr = iptr->sx.s23.s3.c.ref;
disp = dseg_add_unique_address(cd, NULL);
else {
disp = dseg_add_address(cd, super->vftbl);
- M_BEQZ(s1, s3 + 2);
- M_NOP;
+ emit_label_beqz(cd, BRANCH_LABEL_5, s1);
}
M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
#endif
/* } */
M_CMP(REG_ITMP3, REG_ITMP2);
- M_BULT(0); /* branch if ITMP3 < ITMP2 */
- codegen_add_classcastexception_ref(cd, s1);
- M_NOP;
+ emit_classcast_check(cd, iptr, BRANCH_ULT, REG_ITMP3, s1);
+
+ if (super != NULL)
+ emit_label(cd, BRANCH_LABEL_5);
+ }
+
+ if (super == NULL) {
+ emit_label(cd, BRANCH_LABEL_1);
+ emit_label(cd, BRANCH_LABEL_4);
}
d = codegen_reg_of_dst(jd, iptr, s1);
M_NOP;
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- M_BEQZ(REG_RESULT_CALLER, 0);
- codegen_add_classcastexception_ref(cd, s1);
- M_NOP;
+ emit_classcast_check(cd, iptr, ICMD_IFEQ, REG_RESULT_CALLER, s1);
d = codegen_reg_of_dst(jd, iptr, s1);
}
break;
case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
+ /* val.a: (classinfo*) superclass */
/* superclass is an interface:
*
s1 = REG_ITMP1;
}
- /* calculate interface instanceof code size */
-
- s2 = 7;
- if (super == NULL)
- s2 += (opt_shownops ? PATCHER_CALL_INSTRUCTIONS : 0);
-
- /* calculate class instanceof code size */
-
- s3 = 8;
- if (super == NULL)
- s3 += (opt_shownops ? PATCHER_CALL_INSTRUCTIONS : 0);
-
M_CLR(d);
/* if class is not resolved, check which code to call */
if (super == NULL) {
- M_BEQZ(s1, 5 + (opt_shownops ? PATCHER_CALL_INSTRUCTIONS : 0) + s2 + 2 + s3);
- M_NOP;
+ emit_label_beqz(cd, BRANCH_LABEL_1, s1);
cr = iptr->sx.s23.s3.c.ref;
disp = dseg_add_unique_s4(cd, 0); /* super->flags */
M_ILD(REG_ITMP3, REG_PV, disp);
M_AND_IMM(REG_ITMP3, ACC_INTERFACE, REG_ITMP3);
- M_BEQZ(REG_ITMP3, s2 + 2 + 2);
- M_NOP;
+ emit_label_beqz(cd, BRANCH_LABEL_2, REG_ITMP3);
}
/* interface instanceof code */
cr, 0);
}
else {
- M_BEQZ(s1, s2 + 2);
- M_NOP;
+ emit_label_beqz(cd, BRANCH_LABEL_3, s1);
}
M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
superindex * sizeof(methodptr*)));
M_CMOVRNE_IMM(REG_ITMP1, 1, d); /* REG_ITMP1 != 0 */
- if (super == NULL) {
- M_BR(s3 + 2);
- M_NOP;
- }
+ if (super == NULL)
+ emit_label_br(cd, BRANCH_LABEL_4);
+ else
+ emit_label(cd, BRANCH_LABEL_3);
}
/* class instanceof code */
if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
if (super == NULL) {
+ emit_label(cd, BRANCH_LABEL_2);
+
cr = iptr->sx.s23.s3.c.ref;
disp = dseg_add_unique_address(cd, NULL);
else {
disp = dseg_add_address(cd, supervftbl);
- M_BEQZ(s1, s3 + 2);
- M_NOP;
+ emit_label_beqz(cd, BRANCH_LABEL_5, s1);
}
M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
M_SUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
M_CMP(REG_ITMP1, REG_ITMP2);
M_XCMOVULE_IMM(1, d);
+
+ if (super != NULL)
+ emit_label(cd, BRANCH_LABEL_5);
}
+
+ if (super == NULL) {
+ emit_label(cd, BRANCH_LABEL_1);
+ emit_label(cd, BRANCH_LABEL_4);
+ }
+
emit_store_dst(jd, iptr, d);
}
break;
+ case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
+
+ /* check for negative sizes and copy sizes to stack if necessary */
+
+ MCODECHECK((iptr->s1.argcount << 1) + 64);
+
+ for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
+
+ var = VAR(iptr->sx.s23.s2.args[s1]);
+
+ /* copy SAVEDVAR sizes to stack */
+
+ /* Already Preallocated? */
+
+ if (!(var->flags & PREALLOC)) {
+ s2 = emit_load(jd, iptr, var, REG_ITMP1);
+ M_STX(s2, REG_SP, CSTACK + (s1 * 8));
+ }
+ }
+
+ /* arg 0 = dimension count */
+
+ ICONST(REG_OUT0, iptr->s1.argcount);
+
+ /* is patcher function set? */
+
+ if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+ disp = dseg_add_unique_address(cd, 0);
+
+ codegen_add_patch_ref(cd, PATCHER_builtin_multianewarray,
+ iptr->sx.s23.s3.c.ref,
+ disp);
+ }
+ else
+ disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
+
+ /* arg 1 = arraydescriptor */
+
+ M_ALD(REG_OUT1, REG_PV, disp);
+
+ /* arg 2 = pointer to dimensions = stack pointer (absolute) */
+
+ M_ADD_IMM(REG_SP, CSTACK, REG_OUT2);
+
+ /* XXX c abi call */
+ disp = dseg_add_functionptr(cd, BUILTIN_multianewarray);
+ M_ALD(REG_ITMP3, REG_PV, disp);
+ M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
+ M_NOP;
+
+ /* check for exception before result assignment */
+
+ emit_exception_check(cd, iptr);
+
+ d = codegen_reg_of_dst(jd, iptr, REG_RESULT_CALLER);
+ M_INTMOVE(REG_RESULT_CALLER, d);
+ emit_store_dst(jd, iptr, d);
+ break;
default:
exceptions_throw_internalerror("Unknown ICMD %d during code generation",
dseg_createlinenumbertable(cd);
- /* generate exception and patcher stubs */
+ /* generate stubs */
- emit_exception_stubs(jd);
emit_patcher_stubs(jd);
-#if defined(ENABLE_REPLACEMENT)
- emit_replacement_stubs(jd);
-#endif /* defined(ENABLE_REPLACEMENT) */
-
- codegen_finish(jd);
+ REPLACEMENT_EMIT_STUBS(jd);
/* everything's ok */
}
-
-
-
/* createcompilerstub **********************************************************
Creates a stub routine which calls the compiler.
cd = jd->cd;
rd = jd->rd;
- /* rewrite registers and params */
- md_native_reg_setup(jd);
- md_native_param_alloc(nmd);
-
/* initialize variables */
md = m->parseddesc;
#if !defined(WITH_STATIC_CLASSPATH)
if (f == NULL) {
- codegen_addpatchref(cd, PATCHER_resolve_native, m, funcdisp);
-
- if (opt_showdisassemble) {
- M_NOP; M_NOP;
- }
+ codegen_add_patch_ref(cd, PATCHER_resolve_native, m, funcdisp);
}
#endif
for (i = 0, j = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
- M_DST(rd->argfltregs[i], REG_SP, j * 8);
+ M_DST(rd->argfltregs[i], REG_SP, CSTACK + (j * 8));
j++;
}
}
for (i = 0, j = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
- M_DLD(rd->argfltregs[i], REG_SP, j * 8);
+ M_DLD(rd->argfltregs[i], REG_SP, CSTACK + (j * 8));
j++;
}
}
s2 = nat_argintregs[nmd->params[j].regoff];
M_INTMOVE(s1, s2);
} else {
- s2 = nmd->params[j].regoff;
+ s2 = nmd->params[j].regoff - 6;
M_AST(s1, REG_SP, CSTACK + s2 * 8);
}
} else {
s1 = md->params[i].regoff + cd->stackframesize;
- s2 = nmd->params[j].regoff;
+ s2 = nmd->params[j].regoff - 6;
M_ALD(REG_ITMP1, REG_SP, CSTACK + s1 * 8);
M_AST(REG_ITMP1, REG_SP, CSTACK + s2 * 8);
}
M_DMOV(s1, s2 + 16);
fltregarg_inswap[num_fltregargs] = s2;
num_fltregargs++;
- printf("flt arg swap to %d\n", s2 + 16);
+ /*printf("flt arg swap to %d\n", s2 + 16);*/
} else {
s2 = nmd->params[j].regoff;
if (IS_2_WORD_TYPE(t))
- M_DST(s1, REG_SP, CSTACK + s2 * 8);
+ M_DST(s1, REG_SP, CSTACK + (s2 * 8));
else
- M_FST(s1, REG_SP, CSTACK + s2 * 8);
+ M_FST(s1, REG_SP, CSTACK + (s2 * 8));
}
} else {
s1 = md->params[i].regoff + cd->stackframesize;
- s2 = nmd->params[j].regoff;
+ s2 = nmd->params[j].regoff - 6;
if (IS_2_WORD_TYPE(t)) {
M_DLD(REG_FTMP1, REG_SP, CSTACK + s1 * 8);
M_DST(REG_FTMP1, REG_SP, CSTACK + s2 * 8);
for (i = 0; i < num_fltregargs; i++) {
s1 = fltregarg_inswap[i];
M_DMOV(s1 + 16, s1);
- printf("float arg to target reg: %d ==> %d\n", s1+16, s1);
+ /*printf("float arg to target reg: %d ==> %d\n", s1+16, s1);*/
}
}
/* check for exception */
-
M_BNEZ(REG_ITMP2_XPTR, 4); /* if no exception then return */
M_NOP;
M_RETURN(REG_RA_CALLEE, 8); /* implicit window restore */
M_NOP;
-#if 0
- M_RESTORE(REG_ZERO, 0, REG_ZERO); /* restore callers window (DELAY) */
-
- M_RET(REG_RA_CALLER, 8); /* return to caller */
- M_NOP; /* DELAY SLOT */
-#endif
/* handle exception */
disp = dseg_add_functionptr(cd, asm_handle_nat_exception);
- M_ALD(REG_ITMP3, REG_PV, disp); /* load asm exception handler address */
- M_JMP(REG_ZERO, REG_ITMP3, REG_ZERO);/* jump to asm exception handler */
- M_MOV(REG_RA_CALLEE, REG_ITMP3_XPC); /* get exception address (DELAY) */
+ M_ALD(REG_ITMP1, REG_PV, disp); /* load asm exception handler address */
+ M_MOV(REG_RA_CALLEE, REG_ITMP3_XPC); /* get exception address */
+ M_JMP(REG_ZERO, REG_ITMP1, REG_ZERO);/* jump to asm exception handler */
+ M_RESTORE(REG_ZERO, 0, REG_ZERO); /* restore callers window (DELAY) */
+
/* generate patcher stubs */