Optimize and refactor some of mul* Iop code in VEX/priv/host_mips_.
Patch from Aleksandar Rikalo.
return i;
}
-/* multiply */
-MIPSInstr *MIPSInstr_Mul(Bool syned, Bool wid, Bool sz32, HReg dst, HReg srcL,
- HReg srcR)
+/* mul */
+MIPSInstr *MIPSInstr_Mul(HReg dst, HReg srcL, HReg srcR)
{
MIPSInstr *i = LibVEX_Alloc_inline(sizeof(MIPSInstr));
i->tag = Min_Mul;
- i->Min.Mul.syned = syned;
- i->Min.Mul.widening = wid; /* widen=True else False */
- i->Min.Mul.sz32 = sz32; /* True = 32 bits */
i->Min.Mul.dst = dst;
i->Min.Mul.srcL = srcL;
i->Min.Mul.srcR = srcR;
return i;
}
+/* mult, multu / dmult, dmultu */
+MIPSInstr *MIPSInstr_Mult(Bool syned, HReg srcL, HReg srcR)
+{
+ MIPSInstr *i = LibVEX_Alloc_inline(sizeof(MIPSInstr));
+ i->tag = Min_Mult;
+ i->Min.Mult.syned = syned;
+ i->Min.Mult.srcL = srcL;
+ i->Min.Mult.srcR = srcR;
+ return i;
+}
+
+/* ext / dext, dextm, dextu */
+MIPSInstr *MIPSInstr_Ext(HReg dst, HReg src, UInt pos, UInt size)
+{
+ MIPSInstr *i = LibVEX_Alloc_inline(sizeof(MIPSInstr));
+ i->tag = Min_Ext;
+ i->Min.Ext.dst = dst;
+ i->Min.Ext.src = src;
+ i->Min.Ext.pos = pos;
+ i->Min.Ext.size = size;
+ return i;
+}
+
/* msub */
MIPSInstr *MIPSInstr_Msub(Bool syned, HReg srcL, HReg srcR)
{
return;
}
case Min_Mul: {
- switch (i->Min.Mul.widening) {
- case False:
- vex_printf("mul ");
- ppHRegMIPS(i->Min.Mul.dst, mode64);
- vex_printf(", ");
- ppHRegMIPS(i->Min.Mul.srcL, mode64);
- vex_printf(", ");
- ppHRegMIPS(i->Min.Mul.srcR, mode64);
- return;
- case True:
- vex_printf("%s%s ", i->Min.Mul.sz32 ? "mult" : "dmult",
- i->Min.Mul.syned ? "" : "u");
- ppHRegMIPS(i->Min.Mul.dst, mode64);
- vex_printf(", ");
- ppHRegMIPS(i->Min.Mul.srcL, mode64);
- vex_printf(", ");
- ppHRegMIPS(i->Min.Mul.srcR, mode64);
- return;
- }
- break;
+ vex_printf("mul ");
+ ppHRegMIPS(i->Min.Mul.dst, mode64);
+ vex_printf(", ");
+ ppHRegMIPS(i->Min.Mul.srcL, mode64);
+ vex_printf(", ");
+ ppHRegMIPS(i->Min.Mul.srcR, mode64);
+ return;
+ }
+ case Min_Mult: {
+ vex_printf("%s%s ", mode64 ? "dmult" : "mult",
+ i->Min.Mult.syned ? "" : "u");
+ ppHRegMIPS(i->Min.Mult.srcL, mode64);
+ vex_printf(", ");
+ ppHRegMIPS(i->Min.Mult.srcR, mode64);
+ return;
+ }
+ case Min_Ext: {
+ vassert(mode64);
+ vassert(i->Min.Ext.pos < 32);
+ vassert(i->Min.Ext.size > 0);
+ vassert(i->Min.Ext.size <= 32);
+ vassert(i->Min.Ext.size + i->Min.Ext.pos > 0);
+ vassert(i->Min.Ext.size + i->Min.Ext.pos <= 63);
+ vex_printf("dext ");
+ ppHRegMIPS(i->Min.Ext.dst, mode64);
+ vex_printf(", ");
+ ppHRegMIPS(i->Min.Ext.src, mode64);
+ vex_printf(", %u, %u", i->Min.Ext.pos, i->Min.Ext.size);
+ return;
}
case Min_Mthi: {
vex_printf("mthi ");
addHRegUse(u, HRmWrite, i->Min.Mul.dst);
addHRegUse(u, HRmRead, i->Min.Mul.srcL);
addHRegUse(u, HRmRead, i->Min.Mul.srcR);
+ addHRegUse(u, HRmWrite, hregMIPS_HI(mode64));
+ addHRegUse(u, HRmWrite, hregMIPS_LO(mode64));
+ return;
+ case Min_Mult:
+ addHRegUse(u, HRmRead, i->Min.Mult.srcL);
+ addHRegUse(u, HRmRead, i->Min.Mult.srcR);
+ addHRegUse(u, HRmWrite, hregMIPS_HI(mode64));
+ addHRegUse(u, HRmWrite, hregMIPS_LO(mode64));
+ return;
+ case Min_Ext:
+ addHRegUse(u, HRmWrite, i->Min.Ext.dst);
+ addHRegUse(u, HRmRead, i->Min.Ext.src);
return;
case Min_Mthi:
case Min_Mtlo:
mapReg(m, &i->Min.Mul.srcL);
mapReg(m, &i->Min.Mul.srcR);
return;
+ case Min_Mult:
+ mapReg(m, &i->Min.Mult.srcL);
+ mapReg(m, &i->Min.Mult.srcR);
+ return;
+ case Min_Ext:
+ mapReg(m, &i->Min.Ext.src);
+ mapReg(m, &i->Min.Ext.dst);
+ return;
case Min_Mthi:
case Min_Mtlo:
mapReg(m, &i->Min.MtHL.src);
}
case Min_Mul: {
- Bool syned = i->Min.Mul.syned;
- Bool widening = i->Min.Mul.widening;
- Bool sz32 = i->Min.Mul.sz32;
UInt r_srcL = iregNo(i->Min.Mul.srcL, mode64);
UInt r_srcR = iregNo(i->Min.Mul.srcR, mode64);
UInt r_dst = iregNo(i->Min.Mul.dst, mode64);
- if (widening) {
- if (sz32) {
- if (syned)
- /* mult */
- p = mkFormR(p, 0, r_srcL, r_srcR, 0, 0, 24);
- else
- /* multu */
- p = mkFormR(p, 0, r_srcL, r_srcR, 0, 0, 25);
- } else {
- if (syned) /* DMULT r_dst,r_srcL,r_srcR */
- p = mkFormR(p, 0, r_srcL, r_srcR, 0, 0, 28);
- else /* DMULTU r_dst,r_srcL,r_srcR */
- p = mkFormR(p, 0, r_srcL, r_srcR, 0, 0, 29);
- }
+ /* mul r_dst, r_srcL, r_srcR */
+ p = mkFormR(p, 28, r_srcL, r_srcR, r_dst, 0, 2);
+ goto done;
+ }
+
+ case Min_Mult: {
+ Bool syned = i->Min.Mult.syned;
+ UInt r_srcL = iregNo(i->Min.Mult.srcL, mode64);
+ UInt r_srcR = iregNo(i->Min.Mult.srcR, mode64);
+ if (mode64) {
+ if (syned)
+ /* dmult r_srcL, r_srcR */
+ p = mkFormR(p, 0, r_srcL, r_srcR, 0, 0, 28);
+ else
+ /* dmultu r_srcL, r_srcR */
+ p = mkFormR(p, 0, r_srcL, r_srcR, 0, 0, 29);
} else {
- if (sz32)
- /* mul */
- p = mkFormR(p, 28, r_srcL, r_srcR, r_dst, 0, 2);
- else if (mode64 && !sz32)
- p = mkFormR(p, 28, r_srcL, r_srcR, r_dst, 0, 2);
+ if (syned)
+ /* mult r_srcL, r_srcR */
+ p = mkFormR(p, 0, r_srcL, r_srcR, 0, 0, 24);
else
- goto bad;
+ /* multu r_srcL, r_srcR */
+ p = mkFormR(p, 0, r_srcL, r_srcR, 0, 0, 25);
}
goto done;
}
+ case Min_Ext: {
+ UInt r_src = iregNo(i->Min.Ext.src, mode64);
+ UInt r_dst = iregNo(i->Min.Ext.dst, mode64);
+ /* For now, only DEXT is implemented. */
+ vassert(mode64);
+ vassert(i->Min.Ext.pos < 32);
+ vassert(i->Min.Ext.size > 0);
+ vassert(i->Min.Ext.size <= 32);
+ vassert(i->Min.Ext.size + i->Min.Ext.pos > 0);
+ vassert(i->Min.Ext.size + i->Min.Ext.pos <= 63);
+ /* DEXT r_dst, r_src, pos, size */
+ p = mkFormR(p, 0x1F, r_src, r_dst,
+ i->Min.Ext.size - 1, i->Min.Ext.pos, 3);
+ goto done;
+ }
+
case Min_Macc: {
Bool syned = i->Min.Macc.syned;
UInt r_srcL = iregNo(i->Min.Macc.srcL, mode64);
Min_Alu, /* word add/sub/and/or/xor/nor/others? */
Min_Shft, /* word sll/srl/sra */
Min_Unary, /* clo, clz, nop, neg */
+ Min_Ext, /* ext / dext, dextm, dextu */
Min_Cmp, /* word compare (fake insn) */
- Min_Mul, /* widening/non-widening multiply */
+ Min_Mul, /* non-widening, 32-bit, signed multiply */
+ Min_Mult, /* widening multiply */
Min_Div, /* div */
Min_Call, /* call to address in register */
HReg dst;
HReg src;
} Unary;
+ /* Bit extract */
+ struct {
+ HReg dst;
+ HReg src;
+ UInt pos;
+ UInt size;
+ } Ext;
/* Word compare. Fake instruction, used for basic block ending */
struct {
Bool syned;
HReg srcL;
HReg srcR;
} Mul;
+ struct {
+ Bool syned; /* signed/unsigned */
+ HReg srcL;
+ HReg srcR;
+ } Mult;
struct {
Bool syned; /* signed/unsigned - meaningless if widenind = False */
Bool sz32;
extern MIPSInstr *MIPSInstr_Alu(MIPSAluOp, HReg, HReg, MIPSRH *);
extern MIPSInstr *MIPSInstr_Shft(MIPSShftOp, Bool sz32, HReg, HReg, MIPSRH *);
extern MIPSInstr *MIPSInstr_Unary(MIPSUnaryOp op, HReg dst, HReg src);
+extern MIPSInstr *MIPSInstr_Ext(HReg, HReg, UInt, UInt);
extern MIPSInstr *MIPSInstr_Cmp(Bool, Bool, HReg, HReg, HReg, MIPSCondCode);
-extern MIPSInstr *MIPSInstr_Mul(Bool syned, Bool hi32, Bool sz32, HReg,
- HReg, HReg);
+extern MIPSInstr *MIPSInstr_Mul(HReg, HReg, HReg);
+extern MIPSInstr *MIPSInstr_Mult(Bool, HReg, HReg);
extern MIPSInstr *MIPSInstr_Div(Bool syned, Bool sz32, HReg, HReg);
extern MIPSInstr *MIPSInstr_Madd(Bool, HReg, HReg);
extern MIPSInstr *MIPSInstr_Msub(Bool, HReg, HReg);
/* Host CPU has FPU and 32 dbl. prec. FP registers. */
static Bool fp_mode64 = False;
+/* Host hwcaps */
+static UInt hwcaps_host = 0;
+
/* GPR register class for mips32/64 */
#define HRcGPR(_mode64) ((_mode64) ? HRcInt64 : HRcInt32)
return r_dst;
}
- if (e->Iex.Binop.op == Iop_Mul32 || e->Iex.Binop.op == Iop_Mul64) {
- Bool sz32 = (e->Iex.Binop.op == Iop_Mul32);
+ if (e->Iex.Binop.op == Iop_Mul32) {
HReg r_dst = newVRegI(env);
HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
- addInstr(env, MIPSInstr_Mul(False/*Unsigned or Signed */ ,
- False /*widen */ ,
- sz32 /*32bit or 64bit */,
- r_dst, r_srcL, r_srcR));
+ addInstr(env, MIPSInstr_Mul(r_dst, r_srcL, r_srcR));
return r_dst;
}
- if (e->Iex.Binop.op == Iop_MullU32 || e->Iex.Binop.op == Iop_MullS32) {
+ if (e->Iex.Binop.op == Iop_Mul64 ||
+ e->Iex.Binop.op == Iop_MullS32) {
+ vassert(mode64);
HReg r_dst = newVRegI(env);
- HReg tHi = newVRegI(env);
- HReg tLo = newVRegI(env);
- HReg tLo_1 = newVRegI(env);
- HReg tHi_1 = newVRegI(env);
- HReg mask = newVRegI(env);
-
- Bool syned = toBool(e->Iex.Binop.op == Iop_MullS32);
- Bool size = toBool(e->Iex.Binop.op == Iop_MullS32)
- || toBool(e->Iex.Binop.op == Iop_MullU32);
HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
- addInstr(env, MIPSInstr_Mul(syned /*Unsigned or Signed */ ,
- True /*widen */ ,
- size /*32bit or 64bit mul */ ,
- r_dst, r_srcL, r_srcR));
-
- addInstr(env, MIPSInstr_Mfhi(tHi));
- addInstr(env, MIPSInstr_Mflo(tLo));
-
- addInstr(env, MIPSInstr_Shft(Mshft_SLL, False, tHi_1,
- tHi, MIPSRH_Imm(False, 32)));
-
- addInstr(env, MIPSInstr_LI(mask, 0xffffffff));
- addInstr(env, MIPSInstr_Alu(Malu_AND, tLo_1, tLo,
- MIPSRH_Reg(mask)));
-
- addInstr(env, MIPSInstr_Alu(Malu_OR, r_dst, tHi_1,
- MIPSRH_Reg(tLo_1)));
-
+ addInstr(env, MIPSInstr_Mult(True, r_srcL, r_srcR));
+ addInstr(env, MIPSInstr_Mflo(r_dst));
return r_dst;
}
+ if (e->Iex.Binop.op == Iop_MullU32) {
+ vassert(mode64);
+ HReg r_tmpL = newVRegI(env);
+ HReg r_tmpR = newVRegI(env);
+ HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
+ HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
+ if (VEX_MIPS_CPU_HAS_MIPS64R2(hwcaps_host)) {
+ addInstr(env, MIPSInstr_Ext(r_tmpL, r_srcL, 0, 32));
+ addInstr(env, MIPSInstr_Ext(r_tmpR, r_srcR, 0, 32));
+ } else {
+ addInstr(env, MIPSInstr_LI(r_tmpL, 0xFFFFFFFF));
+ addInstr(env, MIPSInstr_Alu(Malu_AND, r_tmpR, r_srcR,
+ MIPSRH_Reg(r_tmpL)));
+ addInstr(env, MIPSInstr_Alu(Malu_AND, r_tmpL, r_srcL,
+ MIPSRH_Reg(r_tmpL)));
+ }
+ addInstr(env, MIPSInstr_Mult(False, r_tmpL, r_tmpR));
+ addInstr(env, MIPSInstr_Mflo(r_tmpR));
+ return r_tmpR;
+ }
+
if (e->Iex.Binop.op == Iop_CmpF64) {
HReg r_srcL, r_srcR;
if (mode64) {
HReg tLo = newVRegI(env);
HReg tHi = newVRegI(env);
Bool syned = toBool(e->Iex.Binop.op == Iop_MullS64);
- HReg r_dst = newVRegI(env);
HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
- addInstr(env, MIPSInstr_Mul(syned, True, False /*64bit mul */ ,
- r_dst, r_srcL, r_srcR));
+ addInstr(env, MIPSInstr_Mult(syned, r_srcL, r_srcR));
addInstr(env, MIPSInstr_Mfhi(tHi));
addInstr(env, MIPSInstr_Mflo(tLo));
*rHi = tHi;
case Iop_MullS32: {
HReg tLo = newVRegI(env);
HReg tHi = newVRegI(env);
- HReg r_dst = newVRegI(env);
Bool syned = toBool(op_binop == Iop_MullS32);
HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
-
- addInstr(env, MIPSInstr_Mul(syned /*Unsigned or Signed */,
- True /*widen */ , True,
- r_dst, r_srcL, r_srcR));
+ addInstr(env, MIPSInstr_Mult(syned, r_srcL, r_srcR));
addInstr(env, MIPSInstr_Mfhi(tHi));
addInstr(env, MIPSInstr_Mflo(tLo));
*rHi = tHi;
Int i, j;
HReg hreg, hregHI;
ISelEnv* env;
- UInt hwcaps_host = archinfo_host->hwcaps;
MIPSAMode *amCounter, *amFailAddr;
+ hwcaps_host = archinfo_host->hwcaps;
+
/* sanity ... */
vassert(arch_host == VexArchMIPS32 || arch_host == VexArchMIPS64);
vassert(VEX_PRID_COMP_MIPS == VEX_MIPS_COMP_ID(hwcaps_host)
/* Check if the processor supports MIPS32R2. */
#define VEX_MIPS_CPU_HAS_MIPS32R2(x) (VEX_MIPS_EX_INFO(x) & \
VEX_MIPS_CPU_ISA_M32R2)
+/* Check if the processor supports MIPS64R2. */
+#define VEX_MIPS_CPU_HAS_MIPS64R2(x) (VEX_MIPS_EX_INFO(x) & \
+ VEX_MIPS_CPU_ISA_M64R2)
/* Check if the processor supports DSP ASE Rev 2. */
#define VEX_MIPS_PROC_DSP2(x) ((VEX_MIPS_COMP_ID(x) == VEX_PRID_COMP_MIPS) && \
(VEX_MIPS_PROC_ID(x) == VEX_PRID_IMP_74K))