diff --git a/coregrind/vg_from_ucode.c b/coregrind/vg_from_ucode.c index 3e8c462d5..94fd72810 100644 --- a/coregrind/vg_from_ucode.c +++ b/coregrind/vg_from_ucode.c @@ -2879,6 +2879,91 @@ static void synth_nonshiftop_lit_offregmem ( Bool simd_flags, } +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) { @@ -3528,6 +3613,30 @@ static void emitUInstr ( UCodeBlock* cb, Int i, 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: diff --git a/coregrind/vg_to_ucode.c b/coregrind/vg_to_ucode.c index 3992e1d82..ef1475582 100644 --- a/coregrind/vg_to_ucode.c +++ b/coregrind/vg_to_ucode.c @@ -271,6 +271,8 @@ static void setFlagsFromUOpcode ( UCodeBlock* cb, Int uopc ) 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: @@ -1446,7 +1448,7 @@ static void codegen_mul_A_D_Reg ( UCodeBlock* cb, Int sz, 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))); @@ -2200,38 +2202,19 @@ Addr dis_mul_E_G ( UCodeBlock* cb, 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), @@ -2239,18 +2222,16 @@ Addr dis_mul_E_G ( UCodeBlock* cb, 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), @@ -2268,30 +2249,20 @@ Addr dis_imul_I_E_G ( UCodeBlock* cb, 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); } @@ -2300,13 +2271,9 @@ Addr dis_imul_I_E_G ( UCodeBlock* cb, 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)) { diff --git a/coregrind/vg_translate.c b/coregrind/vg_translate.c index bb6381685..7863c5968 100644 --- a/coregrind/vg_translate.c +++ b/coregrind/vg_translate.c @@ -461,6 +461,8 @@ Bool VG_(saneUInstr) ( Bool beforeRA, Bool beforeLiveness, UInstr* u ) # 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) @@ -519,6 +521,7 @@ Bool VG_(saneUInstr) ( Bool beforeRA, Bool beforeLiveness, UInstr* u ) 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; @@ -840,6 +843,7 @@ Char* VG_(name_UOpcode) ( Bool upper, Opcode opc ) 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"); @@ -1172,7 +1176,8 @@ void pp_UInstrWorker ( Int instrNo, UInstr* u, Bool ppRegsLiveness ) 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); @@ -1308,6 +1313,7 @@ Int VG_(get_reg_usage) ( UInstr* u, Tag tag, Int* regs, Bool* isWrites ) 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: @@ -1398,6 +1404,7 @@ Int maybe_uinstrReadsArchReg ( UInstr* u ) 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 @@ -1614,6 +1621,7 @@ static void vg_improve ( UCodeBlock* cb ) 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", diff --git a/include/vg_skin.h b/include/vg_skin.h index 697126d1e..d8d168a37 100644 --- a/include/vg_skin.h +++ b/include/vg_skin.h @@ -551,6 +551,7 @@ typedef CMOV, /* Used for cmpxchg and cmov */ /* Arithmetic/logical ops */ + MUL, UMUL, /* Multiply */ ADD, ADC, SUB, SBB, /* Add/subtract (w/wo carry) */ AND, OR, XOR, NOT, /* Boolean ops */ SHL, SHR, SAR, ROL, ROR, RCL, RCR, /* Shift/rotate (w/wo carry) */ diff --git a/memcheck/mc_translate.c b/memcheck/mc_translate.c index ed1acbc57..108a606ab 100644 --- a/memcheck/mc_translate.c +++ b/memcheck/mc_translate.c @@ -860,6 +860,7 @@ static UCodeBlock* memcheck_instrument ( UCodeBlock* cb_in ) */ case ADD: case SUB: case ADC: case SBB: + case MUL: qd = SHADOW(u_in->val2); qs = getOperandShadow(cb, u_in->size, u_in->tag1, u_in->val1); create_UifU(cb, u_in->size, qs, qd);