diff --git a/MCInst.h b/MCInst.h index 6a988b64..36c838e3 100644 --- a/MCInst.h +++ b/MCInst.h @@ -150,6 +150,7 @@ struct MCInst { // A prefix byte gets value 0 when irrelevant. // This is copied from cs_x86 struct uint8_t x86_prefix[5]; + bool x86_lock_rep; // does this X86 insn contain LOCK/REP prefix? }; void MCInst_Init(MCInst *inst); diff --git a/arch/X86/X86Disassembler.c b/arch/X86/X86Disassembler.c index 8a3311b1..f3285d5b 100644 --- a/arch/X86/X86Disassembler.c +++ b/arch/X86/X86Disassembler.c @@ -800,6 +800,10 @@ bool X86_getInstruction(csh ud, const uint8_t *code, size_t code_len, } } + if (insn.prefixPresent[0xf0] || insn.prefixPresent[0xf2] || + insn.prefixPresent[0xf3]) + instr->x86_lock_rep = true; + // save immediate size to print immediate properly instr->x86_imm_size = insn.immediateSize; } diff --git a/arch/X86/X86GenAsmWriter.inc b/arch/X86/X86GenAsmWriter.inc index 5d2745f4..4715e16b 100644 --- a/arch/X86/X86GenAsmWriter.inc +++ b/arch/X86/X86GenAsmWriter.inc @@ -12498,25 +12498,8 @@ static void printInstruction(MCInst *MI, SStream *O, MCRegisterInfo *MRI) uint64_t Bits = (Bits2 << 32) | Bits1; // assert(Bits != 0 && "Cannot print this instruction."); #ifndef CAPSTONE_DIET - int i; - - for(i = 0; i < ARR_SIZE(MI->x86_prefix); i++) { - switch(MI->x86_prefix[i]) { - default: - break; - case 0xf0: - SStream_concat(O, "lock|"); - break; - case 0xf2: - SStream_concat(O, "repne|"); - break; - case 0xf3: - SStream_concat(O, "rep|"); - break; - } - } - - SStream_concat(O, "%s", AsmStrs+(Bits & 16383)-1); + if (!X86_lockrep(MI, O)) + SStream_concat(O, "%s", AsmStrs+(Bits & 16383)-1); #endif diff --git a/arch/X86/X86GenAsmWriter1.inc b/arch/X86/X86GenAsmWriter1.inc index 2b8c3b73..0edafc9e 100644 --- a/arch/X86/X86GenAsmWriter1.inc +++ b/arch/X86/X86GenAsmWriter1.inc @@ -12202,24 +12202,8 @@ static void printInstruction(MCInst *MI, SStream *O, MCRegisterInfo *MRI) uint64_t Bits = (Bits2 << 32) | Bits1; // assert(Bits != 0 && "Cannot print this instruction."); #ifndef CAPSTONE_DIET - int i; - for(i = 0; i < ARR_SIZE(MI->x86_prefix); i++) { - switch(MI->x86_prefix[i]) { - default: - break; - case 0xf0: - SStream_concat(O, "lock|"); - break; - case 0xf2: - SStream_concat(O, "repne|"); - break; - case 0xf3: - SStream_concat(O, "rep|"); - break; - } - } - - SStream_concat(O, "%s", AsmStrs+(Bits & 16383)-1); + if (!X86_lockrep(MI, O)) + SStream_concat(O, "%s", AsmStrs+(Bits & 16383)-1); #endif diff --git a/arch/X86/X86Mapping.c b/arch/X86/X86Mapping.c index 92a7c176..ea360113 100644 --- a/arch/X86/X86Mapping.c +++ b/arch/X86/X86Mapping.c @@ -41706,3 +41706,44 @@ x86_reg X86_insn_reg(unsigned int id) return 0; } +#ifndef CAPSTONE_DIET +// return true if we patch the mnemonic +bool X86_lockrep(MCInst *MI, SStream *O) +{ + int i; + + if (MI->x86_lock_rep) { + for(i = 0; i < ARR_SIZE(MI->x86_prefix); i++) { + switch(MI->x86_prefix[i]) { + default: + break; + case 0xf0: + SStream_concat(O, "lock|"); + break; + case 0xf2: + if (MI->Opcode == X86_MULPDrr) { + MI->Opcode = X86_MULSDrr; + SStream_concat(O, "mulsd\t"); + MI->x86_prefix[i] = 0; + // notify that we already patched mnemonic + return true; + } else + SStream_concat(O, "repne|"); + break; + case 0xf3: + if (MI->Opcode == X86_MULPDrr) { + MI->Opcode = X86_MULSSrr; + SStream_concat(O, "mulss\t"); + MI->x86_prefix[i] = 0; + // notify that we already patched mnemonic + return true; + } else + SStream_concat(O, "rep|"); + break; + } + } + } + + return false; +} +#endif diff --git a/arch/X86/X86Mapping.h b/arch/X86/X86Mapping.h index 7b8848cb..1c7a22c9 100644 --- a/arch/X86/X86Mapping.h +++ b/arch/X86/X86Mapping.h @@ -39,4 +39,10 @@ x86_reg X86_insn_reg(unsigned int id); extern uint64_t arch_masks[9]; +#ifndef CAPSTONE_DIET +// handle LOCK/REP/REPNE prefixes +// return True if we patch mnemonic, like in MULPD case +bool X86_lockrep(MCInst *MI, SStream *O); +#endif + #endif