if (mode64) {
t2 = newTemp(Ity_I64);
- assign(t2, binop(Iop_DivModS64to32,
- getIReg(rs), mkNarrowTo32(ty, getIReg(rt))));
+ assign(t2, binop(Iop_DivModS32to32,
+ mkNarrowTo32(ty, getIReg(rs)),
+ mkNarrowTo32(ty, getIReg(rt))));
putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t2)), True));
putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t2)), True));
} else {
t1 = newTemp(Ity_I64);
- t2 = newTemp(Ity_I64);
- assign(t1, unop(Iop_32Sto64, getIReg(rs)));
- assign(t2, binop(Iop_DivModS64to32, mkexpr(t1), getIReg(rt)));
+ assign(t1, binop(Iop_DivModS32to32, getIReg(rs), getIReg(rt)));
- putHI(unop(Iop_64HIto32, mkexpr(t2)));
- putLO(unop(Iop_64to32, mkexpr(t2)));
+ putHI(unop(Iop_64HIto32, mkexpr(t1)));
+ putLO(unop(Iop_64to32, mkexpr(t1)));
}
break;
if (mode64) {
t2 = newTemp(Ity_I64);
- assign(t2, binop(Iop_DivModU64to32,
- getIReg(rs), mkNarrowTo32(ty, getIReg(rt))));
+ assign(t2, binop(Iop_DivModU32to32,
+ mkNarrowTo32(ty, getIReg(rs)),
+ mkNarrowTo32(ty, getIReg(rt))));
putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t2)), True));
putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t2)), True));
} else {
t1 = newTemp(Ity_I64);
- t2 = newTemp(Ity_I64);
- assign(t1, unop(Iop_32Uto64, getIReg(rs)));
- assign(t2, binop(Iop_DivModU64to32, mkexpr(t1), getIReg(rt)));
- putHI(unop(Iop_64HIto32, mkexpr(t2)));
- putLO(unop(Iop_64to32, mkexpr(t2)));
+
+ assign(t1, binop(Iop_DivModU32to32, getIReg(rs), getIReg(rt)));
+ putHI(unop(Iop_64HIto32, mkexpr(t1)));
+ putLO(unop(Iop_64to32, mkexpr(t1)));
}
break;
case 0x1F: /* Doubleword Divide Unsigned DDIVU; MIPS64 check this */
DIP("ddivu r%u, r%u", rs, rt);
t1 = newTemp(Ity_I128);
- t2 = newTemp(Ity_I128);
- assign(t1, binop(Iop_64HLto128, mkU64(0), getIReg(rs)));
+ assign(t1, binop(Iop_DivModU64to64, getIReg(rs), getIReg(rt)));
- assign(t2, binop(Iop_DivModU128to64, mkexpr(t1), getIReg(rt)));
-
- putHI(unop(Iop_128HIto64, mkexpr(t2)));
- putLO(unop(Iop_128to64, mkexpr(t2)));
+ putHI(unop(Iop_128HIto64, mkexpr(t1)));
+ putLO(unop(Iop_128to64, mkexpr(t1)));
break;
case 0x10: { /* MFHI */
return r_dst;
}
+ if (e->Iex.Binop.op == Iop_DivModU32to32 ||
+ e->Iex.Binop.op == Iop_DivModS32to32) {
+ HReg tLo = newVRegI(env);
+ HReg tHi = newVRegI(env);
+ HReg mask = newVRegI(env);
+ HReg tLo_1 = newVRegI(env);
+ HReg tHi_1 = newVRegI(env);
+ HReg r_dst = newVRegI(env);
+ Bool syned = toBool(e->Iex.Binop.op == Iop_DivModS32to32);
+
+ HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
+ HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
+
+ addInstr(env, MIPSInstr_Div(syned, True, 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)));
+
+ return r_dst;
+ }
+
if (e->Iex.Binop.op == Iop_8HLto16
|| e->Iex.Binop.op == Iop_16HLto32) {
HReg tHi = iselWordExpr_R(env, e->Iex.Binop.arg1);
*rLo = iselWordExpr_R(env, e->Iex.Binop.arg2);
return;
+ case Iop_DivModU64to64:
case Iop_DivModS64to64: {
HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
return;
}
+ case Iop_DivModU32to32:
+ case Iop_DivModS32to32: {
+ HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
+ HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
+ HReg tLo = newVRegI(env);
+ HReg tHi = newVRegI(env);
+ Bool syned = toBool(e->Iex.Binop.op == Iop_DivModS32to32);
+
+ addInstr(env, MIPSInstr_Div(syned, True, r_srcL, r_srcR));
+ addInstr(env, MIPSInstr_Mfhi(tHi));
+ addInstr(env, MIPSInstr_Mflo(tLo));
+ *rHi = tHi;
+ *rLo = tLo;
+ return;
+ }
+
/* 32HLto64(e1,e2) */
case Iop_32HLto64:
*rHi = iselWordExpr_R(env, e->Iex.Binop.arg1);
case Iop_DivModU64to32: vex_printf("DivModU64to32"); return;
case Iop_DivModS64to32: vex_printf("DivModS64to32"); return;
+ case Iop_DivModU32to32: vex_printf("DivModU32to32"); return;
+ case Iop_DivModS32to32: vex_printf("DivModS32to32"); return;
+
case Iop_DivModU128to64: vex_printf("DivModU128to64"); return;
case Iop_DivModS128to64: vex_printf("DivModS128to64"); return;
case Iop_DivModS64to64: vex_printf("DivModS64to64"); return;
+ case Iop_DivModU64to64: vex_printf("DivModU64to64"); return;
case Iop_16HIto8: vex_printf("16HIto8"); return;
case Iop_16to8: vex_printf("16to8"); return;
BINARY(Ity_I64,Ity_I64, Ity_I64);
case Iop_DivModU64to32: case Iop_DivModS64to32:
- BINARY(Ity_I64,Ity_I32, Ity_I64);
+ BINARY(Ity_I64, Ity_I32, Ity_I64);
+
+ case Iop_DivModU32to32: case Iop_DivModS32to32:
+ BINARY(Ity_I32, Ity_I32, Ity_I64);
case Iop_DivModU128to64: case Iop_DivModS128to64:
BINARY(Ity_I128,Ity_I64, Ity_I128);
- case Iop_DivModS64to64:
+ case Iop_DivModU64to64: case Iop_DivModS64to64:
BINARY(Ity_I64,Ity_I64, Ity_I128);
case Iop_16HIto8: case Iop_16to8:
Iop_DivModS64to64, // :: I64,I64 -> I128
// of which lo half is div and hi half is mod
+ Iop_DivModU64to64, // :: I64,I64 -> I128
+ // of which lo half is div and hi half is mod
+ Iop_DivModS32to32, // :: I32,I32 -> I64
+ // of which lo half is div and hi half is mod
+ Iop_DivModU32to32, // :: I32,I32 -> I64
+ // of which lo half is div and hi half is mod
/* Integer conversions. Some of these are redundant (eg
Iop_64to8 is the same as Iop_64to32 and then Iop_32to8), but
case Iop_32HLto64:
return assignNew('V', mce, Ity_I64, binop(op, vatom1, vatom2));
- case Iop_DivModS64to64:
+ case Iop_DivModU64to64:
+ case Iop_DivModS64to64: {
+ IRAtom* vTmp64 = mkLazy2(mce, Ity_I64, vatom1, vatom2);
+ return assignNew('V', mce, Ity_I128,
+ binop(Iop_64HLto128, vTmp64, vTmp64));
+ }
+
case Iop_MullS64:
case Iop_MullU64: {
IRAtom* vLo64 = mkLeft64(mce, mkUifU64(mce, vatom1,vatom2));
binop(Iop_64HLto128, vHi64, vLo64));
}
+ case Iop_DivModU32to32:
+ case Iop_DivModS32to32: {
+ IRAtom* vTmp32 = mkLazy2(mce, Ity_I32, vatom1, vatom2);
+ return assignNew('V', mce, Ity_I64,
+ binop(Iop_32HLto64, vTmp32, vTmp32));
+ }
+
case Iop_MullS32:
case Iop_MullU32: {
IRAtom* vLo32 = mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
// So they cannot be tested in isolation on that platform.
{ DEFOP(Iop_DivModU64to32, UNDEF_ALL), .s390x = 0, .amd64 = 1, .x86 = 1, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 1, .mips64 = 1 },
{ DEFOP(Iop_DivModS64to32, UNDEF_ALL), .s390x = 0, .amd64 = 1, .x86 = 1, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 1, .mips64 = 1 },
+ { DEFOP(Iop_DivModU32to32, UNDEF_ALL), .s390x = 0, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 1, .mips64 = 1 },
+ { DEFOP(Iop_DivModS32to32, UNDEF_ALL), .s390x = 0, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 1, .mips64 = 1 },
{ DEFOP(Iop_DivModU128to64, UNDEF_ALL), .s390x = 0, .amd64 = 1, .x86 = 0, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 0, .mips64 = 1 }, // mips asserts
{ DEFOP(Iop_DivModS128to64, UNDEF_ALL), .s390x = 0, .amd64 = 1, .x86 = 0, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 0, .mips64 = 1 }, // mips asserts
- { DEFOP(Iop_DivModS64to64, UNDEF_ALL), .s390x = 0, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 0, .mips64 = 0 }, // mips asserts
+ { DEFOP(Iop_DivModS64to64, UNDEF_ALL), .s390x = 0, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 0, .mips64 = 1 }, // mips asserts
+ { DEFOP(Iop_DivModU64to64, UNDEF_ALL), .s390x = 0, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 0, .mips64 = 1 }, // mips asserts
{ DEFOP(Iop_8Uto16, UNDEF_ZEXT), .s390x = 1, .amd64 = 1, .x86 = 1, .arm = 0, .ppc64 = 1, .ppc32 = 1, .mips32 = 1, .mips64 = 1 },
{ DEFOP(Iop_8Uto32, UNDEF_ZEXT), .s390x = 1, .amd64 = 1, .x86 = 1, .arm = 1, .ppc64 = 1, .ppc32 = 1, .mips32 = 1, .mips64 = 1 },
{ DEFOP(Iop_8Uto64, UNDEF_ZEXT), .s390x = 1, .amd64 = 1, .x86 = 0, .arm = 0, .ppc64 = 1, .ppc32 = 0, .mips32 = 0, .mips64 = 1 }, // ppc32 assert