}
}
-//--
-//-- /* Generate code to divide ArchRegs EDX:EAX / DX:AX / AX by the 32 /
-//-- 16 / 8 bit quantity in the given TempReg. */
-//-- static
-//-- void codegen_div ( UCodeBlock* cb, Int sz, Int t, Bool signed_divide )
-//-- {
+
+/* Generate code to divide ArchRegs EDX:EAX / DX:AX / AX by the 32 /
+ 16 / 8 bit quantity in the given IRTemp. */
+static
+void codegen_div ( Int sz, IRTemp t, Bool signed_divide )
+{
+ switch (sz) {
+ case 4: {
+ IROp op = signed_divide ? Iop_DivModS64to32 : Iop_DivModU64to32;
+ IRTemp src64 = newTemp(Ity_I64);
+ IRTemp dst64 = newTemp(Ity_I64);
+ assign( src64, binop(Iop_32HLto64,
+ getIReg(4,R_EDX), getIReg(4,R_EAX)) );
+ assign( dst64, binop(op, mkexpr(src64), mkexpr(t)) );
+ putIReg( 4, R_EAX, unop(Iop_64LOto32,mkexpr(dst64)) );
+ putIReg( 4, R_EDX, unop(Iop_64HIto32,mkexpr(dst64)) );
+ break;
+ }
+ default: vpanic("codegen_div(x86)");
+ }
+}
//-- Int helper;
//-- Int ta = newTemp(cb);
//-- Int td = newTemp(cb);
IRType ty = szToITy(sz);
IRTemp t1 = newTemp(ty);
IRTemp t2 = newTemp(ty);
- IRTemp tr = newTemp(ty);
//-- uInstr0(cb, CALLM_S, 0);
//-- uInstr2(cb, GET, sz, ArchReg, eregOfRM(modrm), TempReg, t1);
switch (ty) {
case Ity_I32: {
- IROp hiOp = signed_multiply ? Iop_MullS32_hi32 : Iop_MullU32_hi32;
- IRTemp trHi32 = newTemp(Ity_I32);
- setFlags_MUL ( Ity_I32, t1, t2,
- signed_multiply ? CC_OP_MULLSB : CC_OP_MULLUB );
- assign( tr, binop(Iop_Mul32, mkexpr(t1), mkexpr(t2) ) );
- assign( trHi32, binop(hiOp, mkexpr(t1), mkexpr(t2) ) );
- putIReg(4, R_EAX, mkexpr(tr));
- putIReg(4, R_EDX, mkexpr(trHi32));
+ IRTemp res64 = newTemp(Ity_I64);
+ IROp mulOp = signed_multiply ? Iop_MullS32 : Iop_MullU32;
+ UInt thunkOp = signed_multiply ? CC_OP_MULLSB : CC_OP_MULLUB;
+ setFlags_MUL ( Ity_I32, t1, t2, thunkOp );
+ assign( res64, binop(mulOp, mkexpr(t1), mkexpr(t2)) );
+ putIReg(4, R_EDX, unop(Iop_64HIto32,mkexpr(res64)));
+ putIReg(4, R_EAX, unop(Iop_64LOto32,mkexpr(res64)));
break;
}
default:
//-- case 5: /* IMUL */
//-- codegen_mul_A_D_Temp ( cb, sz, t1, True, dis_buf );
//-- break;
-//-- case 6: /* DIV */
-//-- codegen_div ( cb, sz, t1, False );
-//-- DIP("div%c %s\n", nameISize(sz), dis_buf);
-//-- break;
+ case 6: /* DIV */
+ codegen_div ( sz, t1, False );
+ DIP("div%c %s\n", nameISize(sz), dis_buf);
+ break;
//-- case 7: /* IDIV */
//-- codegen_div ( cb, sz, t1, True );
//-- DIP("idiv%c %s\n", nameISize(sz), dis_buf);
case Iop_Not8 ... Iop_Not64:
str = "Not"; base = Iop_Not8; break;
/* other cases must explicitly "return;" */
- case Iop_8Uto16: vex_printf("8Uto16"); return;
- case Iop_8Uto32: vex_printf("8Uto32"); return;
- case Iop_16Uto32: vex_printf("16Uto32"); return;
- case Iop_8Sto16: vex_printf("8Sto16"); return;
- case Iop_8Sto32: vex_printf("8Sto32"); return;
- case Iop_16Sto32: vex_printf("16Sto32"); return;
- case Iop_32to1: vex_printf("32to1"); return;
- case Iop_1Uto8: vex_printf("1Uto8"); return;
- case Iop_MullS8: vex_printf("MullS8"); return;
- case Iop_MullS16: vex_printf("MullS16"); return;
- case Iop_MullS32_hi32: vex_printf("MullS32_hi32"); return;
- case Iop_MullU8: vex_printf("MullU8"); return;
- case Iop_MullU16: vex_printf("MullU16"); return;
- case Iop_MullU32_hi32: vex_printf("MullU32_hi32"); return;
- default: vpanic("ppIROp(1)");
+ case Iop_8Uto16: vex_printf("8Uto16"); return;
+ case Iop_8Uto32: vex_printf("8Uto32"); return;
+ case Iop_16Uto32: vex_printf("16Uto32"); return;
+ case Iop_8Sto16: vex_printf("8Sto16"); return;
+ case Iop_8Sto32: vex_printf("8Sto32"); return;
+ case Iop_16Sto32: vex_printf("16Sto32"); return;
+ case Iop_32to1: vex_printf("32to1"); return;
+ case Iop_1Uto8: vex_printf("1Uto8"); return;
+
+ case Iop_MullS8: vex_printf("MullS8"); return;
+ case Iop_MullS16: vex_printf("MullS16"); return;
+ case Iop_MullS32: vex_printf("MullS32"); return;
+ case Iop_MullU8: vex_printf("MullU8"); return;
+ case Iop_MullU16: vex_printf("MullU16"); return;
+ case Iop_MullU32: vex_printf("MullU32"); return;
+
+ case Iop_DivModU64to32: vex_printf("DivModU64to32"); return;
+ case Iop_DivModS64to32: vex_printf("DivModS64to32"); return;
+
+ case Iop_64HIto32: vex_printf("64HIto32"); return;
+ case Iop_64LOto32: vex_printf("64LOto32"); return;
+ case Iop_32HLto64: vex_printf("32HLto64"); return;
+
+ default: vpanic("ppIROp(1)");
}
switch (op - base) {
/* Tags for unary ops */
Iop_Not8, Iop_Not16, Iop_Not32, Iop_Not64,
Iop_Neg8, Iop_Neg16, Iop_Neg32, Iop_Neg64,
- /* Conversions */
+ /* Widening multiplies */
+ Iop_MullS8, Iop_MullS16, Iop_MullS32,
+ Iop_MullU8, Iop_MullU16, Iop_MullU32,
+ /* Ordering not important after here. */
+ /* Division */
+ Iop_DivModU64to32, // :: I64,I32 -> I64
+ // of which lo half is div and hi half is mod
+ Iop_DivModS64to32, // ditto, signed
+ /* Widening conversions */
Iop_8Uto16, Iop_8Uto32, Iop_16Uto32,
Iop_8Sto16, Iop_8Sto32, Iop_16Sto32,
- /* Widening multiplies */
- Iop_MullS8, Iop_MullS16, Iop_MullS32_hi32,
- Iop_MullU8, Iop_MullU16, Iop_MullU32_hi32,
+ /* 32 <-> 64 bit conversions */
+ Iop_64LOto32, // :: I64 -> I32, low half
+ Iop_64HIto32, // :: I64 -> I32, high half
+ Iop_32HLto64, // :: (I32,I32) -> I64
/* 1-bit stuff */
Iop_32to1, /* :: Ity_I32 -> Ity_Bit, just select bit[0] */
Iop_1Uto8 /* :: Ity_Bit -> Ity_I8, unsigned widen */