return cf | pf | af | zf | sf | of; \
}
+/* ROL: cf' = msb(result). of' = msb(result) ^ lsb(result). */
+/* DST = result, SRC = old flags */
+#define ACTIONS_ROL(DATA_BITS,DATA_TYPE) \
+{ \
+ PREAMBLE(DATA_BITS); \
+ int fl \
+ = (CC_SRC & ~(CC_O | CC_C)) \
+ | (CC_C & (CC_DST >> (DATA_BITS-1))) \
+ | (CC_O & (lshift(CC_DST, 11-(DATA_BITS-1)) \
+ ^ lshift(CC_DST, 11))); \
+ return fl; \
+}
+
/* ROR: cf' = msb(result). of' = msb(result) ^ msb-1(result). */
/* DST = result, SRC = old flags */
#define ACTIONS_ROR(DATA_BITS,DATA_TYPE) \
return cc_src & (CC_MASK_O | CC_MASK_S | CC_MASK_Z
| CC_MASK_A | CC_MASK_C | CC_MASK_O);
- case CC_OP_ADDB: ACTIONS_ADD( 8, UChar );
+ case CC_OP_ADDB: ACTIONS_ADD( 8, UChar );
case CC_OP_ADDW: ACTIONS_ADD( 16, UShort );
- case CC_OP_ADDL: ACTIONS_ADD( 32, UInt );
+ case CC_OP_ADDL: ACTIONS_ADD( 32, UInt );
- case CC_OP_ADCB: ACTIONS_ADC( 8, UChar );
+ case CC_OP_ADCB: ACTIONS_ADC( 8, UChar );
case CC_OP_ADCW: ACTIONS_ADC( 16, UShort );
- case CC_OP_ADCL: ACTIONS_ADC( 32, UInt );
+ case CC_OP_ADCL: ACTIONS_ADC( 32, UInt );
- case CC_OP_SUBB: ACTIONS_SUB( 8, UChar );
+ case CC_OP_SUBB: ACTIONS_SUB( 8, UChar );
case CC_OP_SUBW: ACTIONS_SUB( 16, UShort );
- case CC_OP_SUBL: ACTIONS_SUB( 32, UInt );
+ case CC_OP_SUBL: ACTIONS_SUB( 32, UInt );
- case CC_OP_SBBB: ACTIONS_SBB( 8, UChar );
+ case CC_OP_SBBB: ACTIONS_SBB( 8, UChar );
case CC_OP_SBBW: ACTIONS_SBB( 16, UShort );
- case CC_OP_SBBL: ACTIONS_SBB( 32, UInt );
+ case CC_OP_SBBL: ACTIONS_SBB( 32, UInt );
- case CC_OP_LOGICB: ACTIONS_LOGIC( 8, UChar );
+ case CC_OP_LOGICB: ACTIONS_LOGIC( 8, UChar );
case CC_OP_LOGICW: ACTIONS_LOGIC( 16, UShort );
- case CC_OP_LOGICL: ACTIONS_LOGIC( 32, UInt );
+ case CC_OP_LOGICL: ACTIONS_LOGIC( 32, UInt );
- case CC_OP_INCB: ACTIONS_INC( 8, UChar );
+ case CC_OP_INCB: ACTIONS_INC( 8, UChar );
case CC_OP_INCW: ACTIONS_INC( 16, UShort );
- case CC_OP_INCL: ACTIONS_INC( 32, UInt );
+ case CC_OP_INCL: ACTIONS_INC( 32, UInt );
- case CC_OP_DECB: ACTIONS_DEC( 8, UChar );
+ case CC_OP_DECB: ACTIONS_DEC( 8, UChar );
case CC_OP_DECW: ACTIONS_DEC( 16, UShort );
- case CC_OP_DECL: ACTIONS_DEC( 32, UInt );
+ case CC_OP_DECL: ACTIONS_DEC( 32, UInt );
+
+ case CC_OP_SHLB: ACTIONS_SHL( 8, UChar );
+ case CC_OP_SHLW: ACTIONS_SHL( 16, UShort );
+ case CC_OP_SHLL: ACTIONS_SHL( 32, UInt );
+
+ case CC_OP_SARB: ACTIONS_SAR( 8, UChar );
+ case CC_OP_SARW: ACTIONS_SAR( 16, UShort );
+ case CC_OP_SARL: ACTIONS_SAR( 32, UInt );
- case CC_OP_SHLL: ACTIONS_SHL( 32, UInt );
- case CC_OP_SARL: ACTIONS_SAR( 32, UInt );
+ case CC_OP_ROLB: ACTIONS_ROL( 8, UChar );
+ case CC_OP_ROLW: ACTIONS_ROL( 16, UShort );
+ case CC_OP_ROLL: ACTIONS_ROL( 32, UInt );
+ case CC_OP_RORB: ACTIONS_ROR( 8, UChar );
case CC_OP_RORW: ACTIONS_ROR( 16, UShort );
- case CC_OP_RORL: ACTIONS_ROR( 32, UInt );
+ case CC_OP_RORL: ACTIONS_ROR( 32, UInt );
case CC_OP_MULL: ACTIONS_MUL( 32, UInt, Long );
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_EAX, unop(Iop_64to32,mkexpr(dst64)) );
putIReg( 4, R_EDX, unop(Iop_64HIto32,mkexpr(dst64)) );
break;
}
vassert(sz == 1 || sz == 2 || sz == 4);
-#if 0
- switch (gregOfRM(modrm)) {
- case 0: op8 = Iop_RolROL; break; case 1: op8 = ROR; break;
- case 2: op8 = RCL; break; case 3: op8 = RCR; break;
- case 4: op8 = Iop_Shl8; break; case 5: op8 = Iop_Shr8; break;
- case 7: op8 = Iop_Sar8; break;
- default: vpanic("dis_Grp2(Reg): unhandled case(x86)");
- }
-#endif
-
/* Put value to shift/rotate in dst0. */
if (epartIsReg(modrm)) {
assign(dst0, getIReg(sz, eregOfRM(modrm)));
isRotate = False;
switch (gregOfRM(modrm)) { case 0: case 1: isRotate = True; }
+ if (!isShift && !isRotate) {
+ vex_printf("\ncase %d\n", gregOfRM(modrm));
+ vpanic("dis_Grp2(Reg): unhandled case(x86)");
+ }
+
if (isShift) {
IRTemp subshift = newTemp(ty);
setFlags_MUL ( Ity_I32, t1, tmp, thunkOp );
assign( res64, binop(mulOp, mkexpr(t1), mkexpr(tmp)) );
putIReg(4, R_EDX, unop(Iop_64HIto32,mkexpr(res64)));
- putIReg(4, R_EAX, unop(Iop_64LOto32,mkexpr(res64)));
+ putIReg(4, R_EAX, unop(Iop_64to32,mkexpr(res64)));
break;
}
default:
tmpRes = newTemp(Ity_I32);
tmpSubSh = newTemp(Ity_I32);
mkpair = Iop_32HLto64;
- getres = left_shift ? Iop_64HIto32 : Iop_64LOto32;
+ getres = left_shift ? Iop_64HIto32 : Iop_64to32;
shift = left_shift ? Iop_Shl64 : Iop_Shr64;
mask = mkU8(31);
- assign( tmpSH, binop(Iop_And8, shift_amt, mask) );
} else {
/* sz == 2 */
- vassert(0);
+ tmpL = newTemp(Ity_I32);
+ tmpRes = newTemp(Ity_I16);
+ tmpSubSh = newTemp(Ity_I16);
+ mkpair = Iop_16HLto32;
+ getres = left_shift ? Iop_32HIto16 : Iop_32to16;
+ shift = left_shift ? Iop_Shl32 : Iop_Shr32;
+ mask = mkU8(15);
}
/* Do the shift, calculate the subshift value, and set
the flag thunk. */
+ assign( tmpSH, binop(Iop_And8, shift_amt, mask) );
+
if (left_shift)
assign( tmpL, binop(mkpair, mkexpr(esrc), mkexpr(gsrc)) );
else
binop(Iop_And8,
binop(Iop_Sub8, mkexpr(tmpSH), mkU8(1) ),
mask))) );
- //assign( guard, binop(Iop_CmpNE8, mkexpr(tmpSH), mkU8(0)) );
- setFlags_DSTus_DST1 (
- left_shift ? Iop_Shl8 : Iop_Sar8,
- tmpSubSh, tmpRes, ty, tmpSH );
+ setFlags_DSTus_DST1 ( left_shift ? Iop_Shl8 : Iop_Sar8,
+ tmpSubSh, tmpRes, ty, tmpSH );
/* Put result back. */
mkU8(d32), NULL );
break;
-//-- case 0xD2: /* Grp2 CL,Eb */
-//-- modrm = getUChar(eip);
-//-- am_sz = lengthAMode(eip);
-//-- d_sz = 0;
-//-- sz = 1;
-//-- eip = dis_Grp2 ( cb, sorb, eip, modrm, am_sz, d_sz, sz, ArchReg, R_ECX );
-//-- break;
+ case 0xD2: /* Grp2 CL,Eb */
+ modrm = getUChar(delta);
+ am_sz = lengthAMode(delta);
+ d_sz = 0;
+ sz = 1;
+ delta = dis_Grp2 ( sorb, delta, modrm, am_sz, d_sz, sz,
+ getIReg(1,R_ECX), "%cl" );
+ break;
case 0xD3: /* Grp2 CL,Ev */
modrm = getIByte(delta);
case Iex_Binop: {
X86AluOp aluOp;
X86ShiftOp shOp;
+
/* Is it an addition or logical style op? */
switch (e->Iex.Binop.op) {
case Iop_Add8: case Iop_Add16: case Iop_Add32:
aluOp = Xalu_ADD; break;
-
case Iop_Sub8: case Iop_Sub16: case Iop_Sub32:
aluOp = Xalu_SUB; break;
-
case Iop_And8: case Iop_And16: case Iop_And32:
aluOp = Xalu_AND; break;
case Iop_Or8: case Iop_Or16: case Iop_Or32:
aluOp = Xalu_OR; break;
-
case Iop_Xor8: case Iop_Xor16: case Iop_Xor32:
aluOp = Xalu_XOR; break;
case Iop_Mul32: aluOp = Xalu_MUL; break;
addInstr(env, X86Instr_Alu32R(aluOp, rmi, dst));
return dst;
}
+
/* Perhaps a shift op? */
switch (e->Iex.Binop.op) {
case Iop_Shl32: case Iop_Shl16: case Iop_Shl8:
shOp = Xsh_SHL; break;
case Iop_Shr32: case Iop_Shr16: case Iop_Shr8:
shOp = Xsh_SHR; break;
- case Iop_Sar32:
+ case Iop_Sar32: case Iop_Sar16: case Iop_Sar8:
shOp = Xsh_SAR; break;
default:
shOp = Xsh_INVALID; break;
}
if (shOp != Xsh_INVALID) {
- HReg dst = newVRegI(env);
+ HReg dst = newVRegI(env);
/* regL = the value to be shifted */
HReg regL = iselIntExpr_R(env, e->Iex.Binop.arg1);
addInstr(env, X86Instr_Alu32R(
Xalu_AND, X86RMI_Imm(0xFFFF), dst));
break;
- case Iop_Sar8: case Iop_Sar16: vassert(0); // fill this in!
+ case Iop_Sar8:
+ addInstr(env, X86Instr_Sh32(Xsh_SHL, 24, X86RM_Reg(dst)));
+ addInstr(env, X86Instr_Sh32(Xsh_SAR, 24, X86RM_Reg(dst)));
+ break;
+ case Iop_Sar16:
+ addInstr(env, X86Instr_Sh32(Xsh_SHL, 16, X86RM_Reg(dst)));
+ addInstr(env, X86Instr_Sh32(Xsh_SAR, 16, X86RM_Reg(dst)));
+ break;
default: break;
}
}
return dst;
}
+
+ /* Handle misc other ops. */
+ if (e->Iex.Binop.op == Iop_16HLto32) {
+ HReg hi16 = newVRegI(env);
+ HReg lo16 = newVRegI(env);
+ HReg hi16s = iselIntExpr_R(env, e->Iex.Binop.arg1);
+ HReg lo16s = iselIntExpr_R(env, e->Iex.Binop.arg2);
+ addInstr(env, mk_MOVsd_RR(hi16s, hi16));
+ addInstr(env, mk_MOVsd_RR(lo16s, lo16));
+ addInstr(env, X86Instr_Sh32(Xsh_SHL, 16, X86RM_Reg(hi16)));
+ addInstr(env, X86Instr_Alu32R(Xalu_AND, X86RMI_Imm(0xFFFF), lo16));
+ addInstr(env, X86Instr_Alu32R(Xalu_OR, X86RMI_Reg(lo16), hi16));
+ return hi16;
+ }
+
break;
}
iselIntExpr64(&rHi,&rLo, env, e->Iex.Unop.arg);
return rHi; /* and abandon rLo .. poor wee thing :-) */
}
- case Iop_64LOto32: {
+ case Iop_64to32: {
HReg rHi, rLo;
iselIntExpr64(&rHi,&rLo, env, e->Iex.Unop.arg);
return rLo; /* similar stupid comment to the above ... */
}
-
+ case Iop_32HIto16: {
+ HReg dst = newVRegI(env);
+ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
+ addInstr(env, mk_MOVsd_RR(src,dst) );
+ addInstr(env, X86Instr_Sh32(Xsh_SHR, 16, X86RM_Reg(dst)));
+ return dst;
+ }
case Iop_32to8:
case Iop_32to16:
/* These are both no-ops. */
case Iop_8Sto32: vex_printf("8Sto32"); return;
case Iop_16Sto32: vex_printf("16Sto32"); return;
case Iop_32to8: vex_printf("32to8"); return;
- case Iop_32to16: vex_printf("32to16"); return;
case Iop_32to1: vex_printf("32to1"); return;
case Iop_1Uto8: vex_printf("1Uto8"); return;
case Iop_DivModU64to32: vex_printf("DivModU64to32"); return;
case Iop_DivModS64to32: vex_printf("DivModS64to32"); return;
+ case Iop_32HIto16: vex_printf("32HIto16"); return;
+ case Iop_32to16: vex_printf("32to16"); return;
+ case Iop_16HLto32: vex_printf("16HLto32"); return;
+
case Iop_64HIto32: vex_printf("64HIto32"); return;
- case Iop_64LOto32: vex_printf("64LOto32"); return;
+ case Iop_64to32: vex_printf("64to32"); return;
case Iop_32HLto64: vex_printf("32HLto64"); return;
default: vpanic("ppIROp(1)");
case Iop_DivModS64to32:
BINARY(Ity_I64,Ity_I64,Ity_I32);
- case Iop_64HIto32: case Iop_64LOto32:
+ case Iop_32HIto16: case Iop_32to16:
+ UNARY(Ity_I16,Ity_I32);
+ case Iop_16HLto32:
+ BINARY(Ity_I32,Ity_I16,Ity_I16);
+
+ case Iop_64HIto32: case Iop_64to32:
UNARY(Ity_I32, Ity_I64);
case Iop_32HLto64:
BINARY(Ity_I64,Ity_I32,Ity_I32);
case Iop_8Uto32: UNARY(Ity_I32,Ity_I8);
case Iop_16Uto32: UNARY(Ity_I32,Ity_I16);
case Iop_32to8: UNARY(Ity_I8,Ity_I32);
- case Iop_32to16: UNARY(Ity_I16,Ity_I32);
default:
ppIROp(op);
Iop_8Uto16, Iop_8Uto32, Iop_16Uto32,
Iop_8Sto16, Iop_8Sto32, Iop_16Sto32,
/* Narrowing conversions */
- Iop_32to16, Iop_32to8,
+ Iop_32to8,
+ /* 16 <-> 32 bit conversions */
+ Iop_32to16, // :: I32 -> I16, low half
+ Iop_32HIto16, // :: I32 -> I16, high half
+ Iop_16HLto32, // :: (I16,I16) -> I32
/* 32 <-> 64 bit conversions */
- Iop_64LOto32, // :: I64 -> I32, low half
+ Iop_64to32, // :: I64 -> I32, low half
Iop_64HIto32, // :: I64 -> I32, high half
Iop_32HLto64, // :: (I32,I32) -> I64
/* 1-bit stuff */