}
+static void synth_mul_reg_reg ( Bool upd_cc,
+ Opcode opcode, Int size,
+ Int reg1, Int reg2 )
+{
+ VG_(new_emit)(upd_cc, FlagsEmpty, FlagsOSZACP);
+
+ switch (size) {
+ case 2:
+ VG_(emitB)(0x66);
+ /* FALLTHROUGH */
+ case 4:
+ VG_(emitB)(0x0F);
+ VG_(emitB)(0xAF);
+ VG_(emit_amode_ereg_greg)(reg1, reg2);
+ break;
+
+ case 1:
+ VG_(core_panic)("can't do byte mul");
+ break;
+ }
+ if (dis)
+ VG_(printf)("\n\t\timul%c\t%s, %s\n",
+ nameISize(size),
+ nameIReg(size, reg1),
+ nameIReg(size, reg2));
+}
+
+static void synth_mul_lit_reg ( Bool upd_cc,
+ Opcode opcode, Int size,
+ UInt lit, Int reg )
+{
+ VG_(new_emit)(upd_cc, FlagsEmpty, FlagsOSZACP);
+
+ switch (size) {
+ case 2:
+ VG_(emitB)(0x66);
+ /* FALLTHROUGH */
+ case 4:
+ VG_(emitB)(0x69);
+ VG_(emit_amode_ereg_greg)(reg, 0);
+ if (size == 2)
+ VG_(emitW)(lit);
+ else
+ VG_(emitL)(lit);
+ break;
+
+ case 1:
+ VG_(core_panic)("can't do byte mul");
+ break;
+ }
+ if (dis)
+ VG_(printf)("\n\t\timul%c\t%d, %s\n",
+ nameISize(size),
+ lit,
+ nameIReg(size, reg));
+}
+
+static void synth_mul_offregmem_reg (
+ Bool upd_cc,
+ Opcode opcode, Int size,
+ Int off, Int areg, Int reg )
+{
+ VG_(new_emit)(upd_cc, FlagsEmpty, FlagsOSZACP);
+
+ switch(size) {
+ case 2:
+ VG_(emitB)(0x66);
+ /* FALLTHROUGH */
+ case 4:
+ VG_(emitB)(0x0F);
+ VG_(emitB)(0xAF);
+ VG_(emit_amode_offregmem_reg)(off, areg, reg);
+ break;
+
+ case 1:
+ VG_(core_panic)("can't do byte mul");
+ }
+
+ if (dis)
+ VG_(printf)("\n\t\timul%c\t0x%x(%s), %s\n",
+ nameISize(size), off, nameIReg(4,areg),nameIReg(size,reg));
+
+}
+
+
static void synth_push_reg ( Int size, Int reg )
{
switch (size) {
break;
}
+ case MUL: {
+ vg_assert(u->tag2 == RealReg);
+
+ switch(u->tag1) {
+ case Literal:
+ synth_mul_lit_reg(anyFlagUse(u),
+ u->opcode, u->size, u->lit32, u->val2);
+ break;
+ case RealReg:
+ synth_mul_reg_reg(anyFlagUse(u),
+ u->opcode, u->size, u->val1, u->val2);
+ break;
+ case ArchReg:
+ synth_mul_offregmem_reg(anyFlagUse(u),
+ u->opcode, u->size,
+ spillOrArchOffset(u->size, u->tag1, u->val1),
+ R_EBP, u->val2);
+ break;
+
+ default: VG_(core_panic)("emitUInstr:MUL");
+ }
+ break;
+ }
+
case SBB:
case ADC:
case XOR:
uFlagsRWU(cb, FlagsEmpty, FlagsOSZCP, FlagA); break;
case ADC: case SBB:
uFlagsRWU(cb, FlagC, FlagsOSZACP, FlagsEmpty); break;
+ case MUL: case UMUL:
+ uFlagsRWU(cb, FlagsEmpty, FlagsOC, FlagsSZAP); break;
case ADD: case SUB: case NEG:
uFlagsRWU(cb, FlagsEmpty, FlagsOSZACP, FlagsEmpty); break;
case INC: case DEC:
uInstr1(cb, POP, 2, TempReg, t1);
uInstr2(cb, PUT, 2, TempReg, t1, ArchReg, R_EAX);
}
- uInstr0(cb, CALLM_E, 0);
+ uInstr0(cb, CALLM_E, 0);
if (dis) VG_(printf)("%s%c %s\n", signed_multiply ? "imul" : "mul",
nameISize(sz), nameIReg(sz, eregOfRM(modrm)));
Addr eip0,
Bool signed_multiply )
{
- Int ta, tg, te, helper;
+ Int ta, tg, te;
UChar dis_buf[50];
UChar rm = getUChar(eip0);
ta = INVALID_TEMPREG;
te = newTemp(cb);
tg = newTemp(cb);
- switch (size) {
- case 4: helper = signed_multiply ? VGOFF_(helper_imul_32_64)
- : VGOFF_(helper_mul_32_64);
- break;
- case 2: helper = signed_multiply ? VGOFF_(helper_imul_16_32)
- : VGOFF_(helper_mul_16_32);
- break;
- case 1: helper = signed_multiply ? VGOFF_(helper_imul_8_16)
- : VGOFF_(helper_mul_8_16);
- break;
- default: VG_(core_panic)("dis_mul_E_G");
- }
-
- uInstr0(cb, CALLM_S, 0);
if (epartIsReg(rm)) {
- uInstr2(cb, GET, size, ArchReg, eregOfRM(rm), TempReg, te);
- uInstr2(cb, GET, size, ArchReg, gregOfRM(rm), TempReg, tg);
- uInstr1(cb, PUSH, size, TempReg, te);
- uInstr1(cb, PUSH, size, TempReg, tg);
- uInstr1(cb, CALLM, 0, Lit16, helper);
- uFlagsRWU(cb, FlagsEmpty, FlagsOC, FlagsSZAP);
- uInstr1(cb, CLEAR, 0, Lit16, 4);
- uInstr1(cb, POP, size, TempReg, tg);
- uInstr2(cb, PUT, size, TempReg, tg, ArchReg, gregOfRM(rm));
- uInstr0(cb, CALLM_E, 0);
+ vg_assert(signed_multiply);
+ uInstr2(cb, GET, size, ArchReg, gregOfRM(rm), TempReg, tg);
+ uInstr2(cb, MUL, size, ArchReg, eregOfRM(rm), TempReg, tg);
+ setFlagsFromUOpcode(cb, MUL);
+ uInstr2(cb, PUT, size, TempReg, tg, ArchReg, gregOfRM(rm));
if (dis) VG_(printf)("%smul%c %s, %s\n",
signed_multiply ? "i" : "",
nameISize(size),
nameIReg(size,gregOfRM(rm)));
return 1+eip0;
} else {
- UInt pair = disAMode ( cb, sorb, eip0, dis?dis_buf:NULL);
+ UInt pair;
+ vg_assert(signed_multiply);
+ pair = disAMode ( cb, sorb, eip0, dis?dis_buf:NULL);
ta = LOW24(pair);
uInstr2(cb, LOAD, size, TempReg, ta, TempReg, te);
uInstr2(cb, GET, size, ArchReg, gregOfRM(rm), TempReg, tg);
- uInstr1(cb, PUSH, size, TempReg, te);
- uInstr1(cb, PUSH, size, TempReg, tg);
- uInstr1(cb, CALLM, 0, Lit16, helper);
- uFlagsRWU(cb, FlagsEmpty, FlagsOC, FlagsSZAP);
- uInstr1(cb, CLEAR, 0, Lit16, 4);
- uInstr1(cb, POP, size, TempReg, tg);
- uInstr2(cb, PUT, size, TempReg, tg, ArchReg, gregOfRM(rm));
- uInstr0(cb, CALLM_E, 0);
+ uInstr2(cb, MUL, size, TempReg, te, TempReg, tg);
+ setFlagsFromUOpcode(cb, MUL);
+ uInstr2(cb, PUT, size, TempReg, tg, ArchReg, gregOfRM(rm));
+
if (dis) VG_(printf)("%smul%c %s, %s\n",
signed_multiply ? "i" : "",
nameISize(size),
Addr eip,
Int litsize )
{
- Int ta, te, tl, helper, d32;
+ Int ta, te, tl, d32;
UChar dis_buf[50];
UChar rm = getUChar(eip);
ta = INVALID_TEMPREG;
te = newTemp(cb);
tl = newTemp(cb);
- switch (size) {
- case 4: helper = VGOFF_(helper_imul_32_64); break;
- case 2: helper = VGOFF_(helper_imul_16_32); break;
- case 1: helper = VGOFF_(helper_imul_8_16); break;
- default: VG_(core_panic)("dis_imul_I_E_G");
- }
-
- uInstr0(cb, CALLM_S, 0);
if (epartIsReg(rm)) {
uInstr2(cb, GET, size, ArchReg, eregOfRM(rm), TempReg, te);
- uInstr1(cb, PUSH, size, TempReg, te);
eip++;
} else {
UInt pair = disAMode ( cb, sorb, eip, dis?dis_buf:NULL);
ta = LOW24(pair);
uInstr2(cb, LOAD, size, TempReg, ta, TempReg, te);
- uInstr1(cb, PUSH, size, TempReg, te);
eip += HI8(pair);
}
uInstr2(cb, MOV, size, Literal, 0, TempReg, tl);
uLiteral(cb, d32);
- uInstr1(cb, PUSH, size, TempReg, tl);
- uInstr1(cb, CALLM, 0, Lit16, helper);
- uFlagsRWU(cb, FlagsEmpty, FlagsOC, FlagsSZAP);
- uInstr1(cb, CLEAR, 0, Lit16, 4);
- uInstr1(cb, POP, size, TempReg, te);
+ uInstr2(cb, MUL, size, TempReg, tl, TempReg, te);
+ setFlagsFromUOpcode(cb, MUL);
uInstr2(cb, PUT, size, TempReg, te, ArchReg, gregOfRM(rm));
- uInstr0(cb, CALLM_E, 0);
if (dis) {
if (epartIsReg(rm)) {
# define Ls3 (u->tag3 == Lit16)
# define TRL1 (TR1 || L1)
# define TRAL1 (TR1 || A1 || L1)
+# define TRA1 (TR1 || A1)
+# define TRA2 (TR2 || A2)
# define N1 (u->tag1 == NoValue)
# define N2 (u->tag2 == NoValue)
# define N3 (u->tag3 == NoValue)
case CLEAR: return LIT0 && SZ0 && CC0 && Ls1 && N2 && N3 && XOTHER;
case AND:
case OR: return LIT0 && SZi && CCa && TR1 && TR2 && N3 && XOTHER;
+ case MUL: return LIT0 && SZ42 && CCa && TRA1 &&TRA2 && N3 && XOTHER;
case ADD:
case XOR:
case SUB: return LITm && SZi && CCa &&TRAL1 && TR2 && N3 && XOTHER;
case ROR: return (upper ? "ROR" : "ror");
case RCL: return (upper ? "RCL" : "rcl");
case RCR: return (upper ? "RCR" : "rcr");
+ case MUL: return (upper ? "MUL" : "mul");
case NOT: return (upper ? "NOT" : "not");
case NEG: return (upper ? "NEG" : "neg");
case INC: return (upper ? "INC" : "inc");
case ADD: case ADC: case AND: case OR:
case XOR: case SUB: case SBB:
case SHL: case SHR: case SAR:
- case ROL: case ROR: case RCL: case RCR:
+ case ROL: case ROR: case RCL: case RCR:
+ case MUL:
VG_(pp_UOperand)(u, 1, u->size, False);
VG_(printf)(", ");
VG_(pp_UOperand)(u, 2, u->size, False);
case CMOV:
case ADD: case ADC: case AND: case OR:
case XOR: case SUB: case SBB:
+ case MUL:
RD(1); RD(2); WR(2); break;
case SHL: case SHR: case SAR:
case XOR: case SUB: case SBB:
case SHL: case SHR: case SAR: case ROL:
case ROR: case RCL: case RCR:
+ case MUL:
if (u->tag1 == ArchReg)
return containingArchRegOf ( u->size, u->val1 );
else
case ADC: case SBB:
case SHL: case SHR: case SAR: case ROL: case ROR:
case RCL: case RCR:
+ case MUL:
if (dis)
VG_(printf)(
" at %2d: change ArchReg %S to TempReg t%d\n",