is Iop_Neg* used?
MOVAPS fix (vg_to_ucode rev 1.143)
check flag settings for cmpxchg
+ check 16/8 bit div/idiv
FUCOMI(P): what happens to A and S flags? Currently are forced
to zero.
*/
static
void codegen_div ( Int sz, IRTemp t, Bool signed_divide )
{
+ IROp op = signed_divide ? Iop_DivModS64to32 : Iop_DivModU64to32;
+ IRTemp src64 = newTemp(Ity_I64);
+ IRTemp dst64 = newTemp(Ity_I64);
switch (sz) {
- case 4: {
- IROp op = signed_divide ? Iop_DivModS64to32 : Iop_DivModU64to32;
- IRTemp src64 = newTemp(Ity_I64);
- IRTemp dst64 = newTemp(Ity_I64);
+ case 4:
assign( src64, binop(Iop_32HLto64,
- getIReg(4,R_EDX), getIReg(4,R_EAX)) );
+ getIReg(4,R_EDX), getIReg(4,R_EAX)) );
assign( dst64, binop(op, mkexpr(src64), mkexpr(t)) );
putIReg( 4, R_EAX, unop(Iop_64to32,mkexpr(dst64)) );
putIReg( 4, R_EDX, unop(Iop_64HIto32,mkexpr(dst64)) );
break;
+ case 2: {
+ IROp widen3264 = signed_divide ? Iop_32Sto64 : Iop_32Uto64;
+ IROp widen1632 = signed_divide ? Iop_16Sto32 : Iop_16Uto32;
+ assign( src64, unop(widen3264,
+ binop(Iop_16HLto32,
+ getIReg(2,R_EDX), getIReg(2,R_EAX))) );
+ assign( dst64, binop(op, mkexpr(src64), unop(widen1632,mkexpr(t))) );
+ putIReg( 2, R_EAX, unop(Iop_32to16,unop(Iop_64to32,mkexpr(dst64))) );
+ putIReg( 2, R_EDX, unop(Iop_32to16,unop(Iop_64HIto32,mkexpr(dst64))) );
+ break;
}
default: vpanic("codegen_div(x86)");
}
return;
}
+ /* 32Uto64(e) */
+ if (e->tag == Iex_Unop
+ && e->Iex.Unop.op == Iop_32Uto64) {
+ HReg tLo = newVRegI(env);
+ HReg tHi = newVRegI(env);
+ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
+ addInstr(env, mk_MOVsd_RR(src,tLo));
+ addInstr(env, X86Instr_Alu32R(Xalu_MOV, X86RMI_Imm(0), tHi));
+ *rHi = tHi;
+ *rLo = tLo;
+ return;
+ }
+
/* 64-bit shifts */
if (e->tag == Iex_Binop
&& e->Iex.Binop.op == Iop_Shl64) {
case Iop_8Sto32: vex_printf("8Sto32"); return;
case Iop_16Sto32: vex_printf("16Sto32"); return;
case Iop_32Sto64: vex_printf("32Sto64"); return;
+ case Iop_32Uto64: vex_printf("32Uto64"); return;
case Iop_32to8: vex_printf("32to8"); return;
case Iop_32to1: vex_printf("32to1"); return;
case Iop_1Uto8: vex_printf("1Uto8"); return;
case Iop_16Uto32: UNARY(Ity_I32,Ity_I16);
case Iop_16Sto32: UNARY(Ity_I32,Ity_I16);
case Iop_32Sto64: UNARY(Ity_I64,Ity_I32);
+ case Iop_32Uto64: UNARY(Ity_I64,Ity_I32);
case Iop_32to8: UNARY(Ity_I8,Ity_I32);
case Iop_PRemF64:
// of which lo half is div and hi half is mod
Iop_DivModS64to32, // ditto, signed
/* Widening conversions */
- Iop_8Uto16, Iop_8Uto32, Iop_16Uto32,
+ Iop_8Uto16, Iop_8Uto32, Iop_16Uto32, Iop_32Uto64,
Iop_8Sto16, Iop_8Sto32, Iop_16Sto32, Iop_32Sto64,
/* Narrowing conversions */
Iop_32to8,