*/
#define REG_PV REG_PV_CALLEE
-static int fabort(char *x)
-{
- fprintf(stderr, "sparc64 abort because: %s\n", x);
- exit(1);
- abort();
- return 0;
-
-}
/* codegen *********************************************************************
unresolved_method *um;
builtintable_entry *bte;
methoddesc *md;
+ fieldinfo *fi;
+ unresolved_field *uf;
rplpoint *replacementpoint;
s4 fieldtype;
s4 varindex;
{
s4 i, p, t, l;
- s4 savedregs_num;
+ s4 savedregs_num, localbase;
#if 0 /* no leaf optimization yet */
savedregs_num = (jd->isleafmethod) ? 0 : 1; /* space to save the RA */
if (cd->stackframesize)
M_SAVE(REG_SP, -cd->stackframesize * 8, REG_SP);
- /* save callee saved float registers */
+ /* save callee saved float registers (none right now) */
+#if 0
p = cd->stackframesize;
for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
p--; M_DST(rd->savfltregs[i], REG_SP, USESTACK + (p * 8));
- }
+ }
+#endif
+
+#if !defined(NDEBUG)
+ if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
+ emit_verbosecall_enter(jd);
+#endif
+
/* take arguments out of register or stack frame */
md = m->parseddesc;
/* when storing locals, use this as base */
- int localbase = USESTACK;
+ localbase = USESTACK;
/* since the register allocator does not know about the shifting window
* arg regs need to be copied via the stack
M_LDX(var->vv.regoff, REG_FP, (WINSAVE_CNT + s1) * 8);
} else { /* stack arg -> spilled */
+ assert(0); /* XXX winsave area in between */
var->vv.regoff = cd->stackframesize + s1;
}
}
M_DLD(var->vv.regoff, REG_FP, (WINSAVE_CNT + s1) * 8);
} else { /* stack-arg -> spilled */
+ assert(0); /* XXX winsave area in between */
var->vv.regoff = cd->stackframesize + s1;
}
}
/* XXX monitor enter */
-#if !defined(NDEBUG)
- if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
- emit_verbosecall_enter(jd);
-#endif
+
}
case ICMD_I2D:
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_FTMP2, REG_PV_CALLEE, disp); /* REG_FTMP2 needs to be a double temp */
- M_CVTLF (REG_FTMP2, d); /* rd gets translated to double target register */
+ disp = dseg_add_float(cd, 0.0);
+ M_IST (s1, REG_PV_CALLEE, disp);
+ M_FLD (REG_FTMP2, REG_PV_CALLEE, disp); /* REG_FTMP2 needs to be a double temp */
+ M_CVTID (REG_FTMP2, d); /* rd gets translated to double target register */
emit_store_dst(jd, iptr, d);
break;
case ICMD_GETSTATIC: /* ... ==> ..., value */
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
- unresolved_field *uf = iptr->sx.s23.s3.uf;
+ uf = iptr->sx.s23.s3.uf;
fieldtype = uf->fieldref->parseddesc.fd->type;
disp = dseg_add_unique_address(cd, uf);
codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
}
else {
- fieldinfo *fi = iptr->sx.s23.s3.fmiref->p.field;
+ fi = iptr->sx.s23.s3.fmiref->p.field;
fieldtype = fi->type;
disp = dseg_add_address(cd, &(fi->value));
case ICMD_PUTSTATIC: /* ..., value ==> ... */
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
- unresolved_field *uf = iptr->sx.s23.s3.uf;
-
+ uf = iptr->sx.s23.s3.uf;
fieldtype = uf->fieldref->parseddesc.fd->type;
disp = dseg_add_unique_address(cd, uf);
codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
}
else {
- fieldinfo *fi = iptr->sx.s23.s3.fmiref->p.field;
+ fi = iptr->sx.s23.s3.fmiref->p.field;
fieldtype = fi->type;
disp = dseg_add_address(cd, &(fi->value));
gen_nullptr_check(s1);
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
- unresolved_field *uf = iptr->sx.s23.s3.uf;
+ uf = iptr->sx.s23.s3.uf;
fieldtype = uf->fieldref->parseddesc.fd->type;
+ disp = 0;
- codegen_addpatchref(cd, PATCHER_get_putfield,
- iptr->sx.s23.s3.uf, 0);
-
- if (opt_showdisassemble) {
- M_NOP; M_NOP;
- }
-
- disp = 0;
-
- } else {
- disp = iptr->sx.s23.s3.fmiref->p.field->offset;
+ codegen_add_patch_ref(cd, PATCHER_get_putfield, uf, 0);
+ }
+ else {
+ fieldinfo *fi = iptr->sx.s23.s3.fmiref->p.field;
+ fieldtype = fi->type;
+ disp = fi->offset;
}
switch (fieldtype) {
case TYPE_INT:
d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
M_ILD(d, s1, disp);
- emit_store_dst(jd, iptr, d);
break;
case TYPE_LNG:
d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
M_LDX(d, s1, disp);
- emit_store_dst(jd, iptr, d);
break;
case TYPE_ADR:
d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
M_ALD(d, s1, disp);
- emit_store_dst(jd, iptr, d);
break;
case TYPE_FLT:
d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
M_FLD(d, s1, disp);
- emit_store_dst(jd, iptr, d);
break;
case TYPE_DBL:
d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
M_DLD(d, s1, disp);
- emit_store_dst(jd, iptr, d);
+ break;
+ default:
+ assert(0);
break;
}
+ emit_store_dst(jd, iptr, d);
break;
case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
- s1 = emit_load_s1(jd, iptr, REG_ITMP2);
+ s1 = emit_load_s1(jd, iptr, REG_ITMP1);
gen_nullptr_check(s1);
- /*if (!IS_FLT_DBL_TYPE(fieldtype)) {
- s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- } else {*/
- s2 = emit_load_s2(jd, iptr, REG_IFTMP);
- /*}*/
-
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
- unresolved_field *uf = iptr->sx.s23.s3.uf;
-
+ uf = iptr->sx.s23.s3.uf;
fieldtype = uf->fieldref->parseddesc.fd->type;
-
- codegen_addpatchref(cd, PATCHER_get_putfield,
- iptr->sx.s23.s3.uf, 0);
-
- if (opt_showdisassemble) {
- M_NOP; M_NOP;
+ disp = 0;
+ }
+ else {
+ uf = NULL;
+ fi = iptr->sx.s23.s3.fmiref->p.field;
+ fieldtype = fi->type;
+ disp = fi->offset;
}
- disp = 0;
+ if (IS_INT_LNG_TYPE(fieldtype))
+ s2 = emit_load_s2(jd, iptr, REG_ITMP2);
+ else
+ s2 = emit_load_s2(jd, iptr, REG_FTMP2);
- } else {
- disp = iptr->sx.s23.s3.fmiref->p.field->offset;
- }
+ if (INSTRUCTION_IS_UNRESOLVED(iptr))
+ codegen_add_patch_ref(cd, PATCHER_get_putfield, uf, 0);
switch (fieldtype) {
case TYPE_INT:
case TYPE_DBL:
M_DST(s2, s1, disp);
break;
+ default:
+ assert(0);
+ break;
}
break;
bte = iptr->sx.s23.s3.bte;
md = bte->md;
- assert(md->paramcount <= 5);
+
+ /* XXX: proper builtin calling and float args are so not implemented */
+ assert(md->paramcount <= 5 && md->argfltreguse < 1);
+
goto gen_method;
case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
}
/* copy or spill arguments to new locations */
-
+ int num_fltregargs = 0;
+ int fltregarg_inswap[16];
for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
t = md->paramtypes[i].type;
s1 = REG_WINDOW_TRANSPOSE(s1);
if (!nmd->params[j].inmemory) {
- s2 = rd->argintregs[nmd->params[j].regoff];
+ s2 = nat_argintregs[nmd->params[j].regoff];
M_INTMOVE(s1, s2);
} else {
s2 = nmd->params[j].regoff;
s1 = rd->argfltregs[md->params[i].regoff];
if (!nmd->params[j].inmemory) {
- s2 = rd->argfltregs[nmd->params[j].regoff];
- if (IS_2_WORD_TYPE(t))
- M_DMOV(s1, s2);
- else
- M_DMOV(s1, s2);
+ /* no mapping to regs needed, native flt args use regoff */
+ s2 = nmd->params[j].regoff;
+
+ /* we cannot move flt regs to their native arg locations directly */
+ M_DMOV(s1, s2 + 16);
+ fltregarg_inswap[num_fltregargs] = s2;
+ num_fltregargs++;
+ printf("flt arg swap to %d\n", s2 + 16);
} else {
s2 = nmd->params[j].regoff;
}
}
}
+
+ /* move swapped float args to target regs */
+ for (i = 0; i < num_fltregargs; i++) {
+ s1 = fltregarg_inswap[i];
+ M_DMOV(s1 + 16, s1);
+ printf("float arg to target reg: %d ==> %d\n", s1+16, s1);
+ }
/* put class into second argument register */
else
M_DST(REG_FRESULT, REG_SP, USESTACK_PARAMS);
}
+
+ /* Note: native functions return float values in %f0 (see ABI) */
+ /* we handle this by doing M_FLD below. (which will load the lower word into %f1) */
#if !defined(NDEBUG)
- if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
+ /* But for the trace function we need to put a flt result into %f1 */
+ if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
+ if (!IS_2_WORD_TYPE(md->returntype.type))
+ M_FLD(REG_FRESULT, REG_SP, USESTACK_PARAMS);
emit_verbosecall_exit(jd);
+ }
#endif
/* remove native stackframe info */
if (md->returntype.type != TYPE_VOID) {
if (IS_FLT_DBL_TYPE(md->returntype.type)) {
- M_DLD(REG_FRESULT, REG_SP, USESTACK_PARAMS);
+ if (IS_2_WORD_TYPE(md->returntype.type))
+ M_DLD(REG_FRESULT, REG_SP, USESTACK_PARAMS);
+ else
+ M_FLD(REG_FRESULT, REG_SP, USESTACK_PARAMS);
}
}
#include "vm/jit/jit.h"
+/* from md-abi.c */
+s4 nat_argintregs[INT_NATARG_CNT];
+
/* branch defines *************************************************************/
#define BRANCH_NOPS \
} while (0)
+#define FR_X(r) (((r)<<2) + 1)
+#define DR_X(r) (((r)<<2)|((r)>>5))
+
/* 3-address-floating-point-operation
- op .... opcode
- op3,opf .... function-number
- rd .... dest reg
- rs2 ... source reg
-
- !!! 6-bit to 5-bit conversion done here !!!
-*/
+ * op .... opcode
+ * op3,opf .... function-number
+ * rd .... dest reg
+ * rs1 ... source reg (-1 signals unused)
+ * rs2 ... source reg
+ *
+ *
+ */
#define M_FOP3(op,op3,opf,rd,rs1,rs2) \
do { \
- *((u4 *) cd->mcodeptr) = ( (((s4)(op))<<30) | ((rd*2)<<25) | ((op3)<<19) | ((rs1*2) << 14) | ((opf)<<5) | (rs2*2) ); \
+ *((u4 *) cd->mcodeptr) = ( (((s4)(op))<<30) | ((rd)<<25) | ((op3)<<19) | ((((rs1)==-1)?0:(rs1)) << 14) | \
+ ((opf)<<5) | (rs2) ); \
+ cd->mcodeptr += 4; \
+ } while (0)
+/* float addressing */
+#define M_FOP3_FX(op,op3,opf,rd,rs1,rs2) \
+ do { \
+ *((u4 *) cd->mcodeptr) = ( (((s4)(op))<<30) | (FR_X(rd)<<25) | ((op3)<<19) | ((((rs1)==-1)?0:FR_X(rs1)) << 14) | \
+ ((opf)<<5) | FR_X(rs2) ); \
+ cd->mcodeptr += 4; \
+ } while (0)
+/* double addressing */
+#define M_FOP3_DX(op,op3,opf,rd,rs1,rs2) \
+ do { \
+ *((u4 *) cd->mcodeptr) = ( (((s4)(op))<<30) | (DR_X(rd)<<25) | ((op3)<<19) | ((((rs1)==-1)?0:DR_X(rs1)) << 14) | \
+ ((opf)<<5) | DR_X(rs2) ); \
cd->mcodeptr += 4; \
} while (0)
-
/**** format 2 operations ********/
/**** floating point operations **/
-#define M_DMOV(rs,rd) M_FOP3(0x02,0x34,0x02,rd,0,rs) /* rd = rs */
-#define M_FMOV(rs,rd) M_FOP3(0x02,0x34,0x01,rd,0,rs) /* rd = rs */
+#define M_DMOV(rs,rd) M_FOP3_DX(0x02,0x34,0x02,rd,-1,rs) /* rd = rs */
+#define M_FMOV(rs,rd) M_FOP3_FX(0x02,0x34,0x01,rd,-1,rs) /* rd = rs */
-#define M_FNEG(rs,rd) M_FOP3(0x02,0x34,0x05,rd,0,rs) /* rd = -rs */
-#define M_DNEG(rs,rd) M_FOP3(0x02,0x34,0x06,rd,0,rs) /* rd = -rs */
+#define M_FNEG(rs,rd) M_FOP3_FX(0x02,0x34,0x05,rd,-1,rs) /* rd = -rs */
+#define M_DNEG(rs,rd) M_FOP3_DX(0x02,0x34,0x06,rd,-1,rs) /* rd = -rs */
-#define M_FADD(rs1,rs2,rd) M_FOP3(0x02,0x34,0x41,rd,rs1,rs2) /* float add */
-#define M_DADD(rs1,rs2,rd) M_FOP3(0x02,0x34,0x42,rd,rs1,rs2) /* double add */
-#define M_FSUB(rs1,rs2,rd) M_FOP3(0x02,0x34,0x045,rd,rs1,rs2) /* float sub */
-#define M_DSUB(rs1,rs2,rd) M_FOP3(0x02,0x34,0x046,rd,rs1,rs2) /* double sub */
-#define M_FMUL(rs1,rs2,rd) M_FOP3(0x02,0x34,0x049,rd,rs1,rs2) /* float mul */
-#define M_DMUL(rs1,rs2,rd) M_FOP3(0x02,0x34,0x04a,rd,rs1,rs2) /* double mul */
-#define M_FDIV(rs1,rs2,rd) M_FOP3(0x02,0x34,0x04d,rd,rs1,rs2) /* float div */
-#define M_DDIV(rs1,rs2,rd) M_FOP3(0x02,0x34,0x04e,rd,rs1,rs2) /* double div */
+#define M_FADD(rs1,rs2,rd) M_FOP3_FX(0x02,0x34,0x41,rd,rs1,rs2) /* float add */
+#define M_DADD(rs1,rs2,rd) M_FOP3_DX(0x02,0x34,0x42,rd,rs1,rs2) /* double add */
+#define M_FSUB(rs1,rs2,rd) M_FOP3_FX(0x02,0x34,0x045,rd,rs1,rs2) /* float sub */
+#define M_DSUB(rs1,rs2,rd) M_FOP3_DX(0x02,0x34,0x046,rd,rs1,rs2) /* double sub */
+#define M_FMUL(rs1,rs2,rd) M_FOP3_FX(0x02,0x34,0x049,rd,rs1,rs2) /* float mul */
+#define M_DMUL(rs1,rs2,rd) M_FOP3_DX(0x02,0x34,0x04a,rd,rs1,rs2) /* double mul */
+#define M_FDIV(rs1,rs2,rd) M_FOP3_FX(0x02,0x34,0x04d,rd,rs1,rs2) /* float div */
+#define M_DDIV(rs1,rs2,rd) M_FOP3_DX(0x02,0x34,0x04e,rd,rs1,rs2) /* double div */
/**** compare and conditional FPU operations ***********/
/* rd field 0 ==> fcc target unit is fcc0 */
-#define M_FCMP(rs1,rs2) M_FOP3(0x02,0x35,0x051,0,rs1,rs2) /* set fcc flt */
-#define M_DCMP(rs1,rs2) M_FOP3(0x02,0x35,0x052,0,rs1,rs2) /* set fcc dbl */
+#define M_FCMP(rs1,rs2) M_FOP3_FX(0x02,0x35,0x051,0,rs1,rs2) /* set fcc flt */
+#define M_DCMP(rs1,rs2) M_FOP3_DX(0x02,0x35,0x052,0,rs1,rs2) /* set fcc dbl */
/* conversion functions */
-#define M_CVTIF(rs,rd) M_FOP3(0x02,0x34,0x0c4,rd,0,rs)/* int2flt */
-#define M_CVTID(rs,rd) M_FOP3(0x02,0x34,0x0c8,rd,0,rs) /* int2dbl */
-#define M_CVTLF(rs,rd) M_FOP3(0x02,0x34,0x084,rd,0,rs) /* long2flt */
-#define M_CVTLD(rs,rd) M_FOP3(0x02,0x34,0x088,rd,0,rs) /* long2dbl */
+#define M_CVTIF(rs,rd) M_FOP3_FX(0x02,0x34,0x0c4,rd,-1,rs)/* int2flt */
+#define M_CVTID(rs,rd) M_FOP3(0x02,0x34,0x0c8,DR_X(rd),-1,FR_X(rs)) /* int2dbl */
+#define M_CVTLF(rs,rd) M_FOP3(0x02,0x34,0x084,FR_X(rd),-1,DR_X(rs)) /* long2flt */
+#define M_CVTLD(rs,rd) M_FOP3_DX(0x02,0x34,0x088,rd,-1,rs) /* long2dbl */
-#define M_CVTFI(rs,rd) M_FOP3(0x02,0x34,0x0d1,rd,0,rs) /* flt2int */
-#define M_CVTDI(rs,rd) M_FOP3(0x02,0x34,0x0d2,rd,0,rs) /* dbl2int */
-#define M_CVTFL(rs,rd) M_FOP3(0x02,0x34,0x081,rd,0,rs) /* flt2long */
-#define M_CVTDL(rs,rd) M_FOP3(0x02,0x34,0x082,rd,0,rs) /* dbl2long */
+#define M_CVTFI(rs,rd) M_FOP3_FX(0x02,0x34,0x0d1,rd,-1,rs) /* flt2int */
+#define M_CVTDI(rs,rd) M_FOP3(0x02,0x34,0x0d2,FR_X(rd),-1,DR_X(rs)) /* dbl2int */
+#define M_CVTFL(rs,rd) M_FOP3(0x02,0x34,0x081,DR_X(rd),-1,FR_X(rs)) /* flt2long */
+#define M_CVTDL(rs,rd) M_FOP3_DX(0x02,0x34,0x082,rd,-1,rs) /* dbl2long */
-#define M_CVTFD(rs,rd) M_FOP3(0x02,0x34,0x0c9,rd,0,rs) /* flt2dbl */
-#define M_CVTDF(rs,rd) M_FOP3(0x02,0x34,0x0c6,rd,0,rs) /* dbl2float */
+#define M_CVTFD(rs,rd) M_FOP3(0x02,0x34,0x0c9,DR_X(rs),-1,FR_X(rs)) /* flt2dbl */
+#define M_CVTDF(rs,rd) M_FOP3(0x02,0x34,0x0c6,FR_X(rs),-1,DR_X(rs)) /* dbl2float */
-/* a 6-bit double register index has to be converted into the 5-bit representation
- * (%d1 -> %f2, %d2 -> %f4, ie. shift left once )
- * don't have to pack the MSB, since we are not using the upper 16 doubles
- *
- * since single precision floats reside in the lower register of a double pair their
- * register numbers need to be handled in the same way
- */
-/* M_OP3 will not do the floar register number conversion */
-#define M_DLD_INTERN(rd,rs1,disp) M_OP3(0x03,0x23,rd*2,rs1,disp,IMM) /* double (64-bit) load */
+#define M_DLD_INTERN(rd,rs1,disp) M_OP3(0x03,0x23,DR_X(rd),rs1,disp,IMM) /* double (64-bit) load */
#define M_DLD(rd,rs,disp) \
do { \
s4 lo = (short) (disp); \
} while (0)
/* Note for SETHI: sethi has a 22bit imm, only set upper 19 bits */
-#define M_FLD_INTERN(rd,rs1,disp) M_OP3(0x03,0x20,rd*2,rs1,disp,IMM) /* float (32-bit) load */
+#define M_FLD_INTERN(rd,rs1,disp) M_OP3(0x03,0x20,FR_X(rd),rs1,disp,IMM) /* float (32-bit) load */
#define M_FLD(rd,rs,disp) \
do { \
s4 lo = (short) (disp); \
} while (0)
-#define M_FST_INTERN(rd,rs,disp) M_OP3(0x03,0x24,rd*2,rs,disp,IMM) /* float (32-bit) store */
+#define M_FST_INTERN(rd,rs,disp) M_OP3(0x03,0x24,FR_X(rd),rs,disp,IMM) /* float (32-bit) store */
#define M_FST(rd,rs,disp) \
do { \
s4 lo = (short) (disp); \
} while (0)
-#define M_DST_INTERN(rd,rs1,disp) M_OP3(0x03,0x27,rd*2,rs1,disp,IMM) /* double (64-bit) store */
+#define M_DST_INTERN(rd,rs1,disp) M_OP3(0x03,0x27,DR_X(rd),rs1,disp,IMM) /* double (64-bit) store */
#define M_DST(rd,rs,disp) \
do { \
s4 lo = (short) (disp); \