From 85026d937558b1ab5f8e84ee756ed925459085e2 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Thu, 16 Jan 2014 07:36:58 +0000 Subject: [PATCH] Allow x86 mov instructions to/from memory with absolute address to be encoded and disassembled with a segment override prefix. Fixes PR16962. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@199364 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/AsmParser/X86AsmParser.cpp | 11 ++-- .../X86/Disassembler/X86Disassembler.cpp | 29 +++++++---- .../X86/InstPrinter/X86ATTInstPrinter.cpp | 7 +++ .../X86/InstPrinter/X86IntelInstPrinter.cpp | 7 +++ lib/Target/X86/MCTargetDesc/X86BaseInfo.h | 5 ++ .../X86/MCTargetDesc/X86MCCodeEmitter.cpp | 33 +++++++----- lib/Target/X86/X86InstrFormats.td | 2 +- lib/Target/X86/X86InstrInfo.td | 52 ++++++++++--------- test/MC/Disassembler/X86/x86-32.txt | 3 ++ test/MC/X86/x86-16.s | 3 +- test/MC/X86/x86-32.s | 6 ++- utils/TableGen/X86RecognizableInstr.cpp | 32 +++++++++++- 12 files changed, 130 insertions(+), 60 deletions(-) diff --git a/lib/Target/X86/AsmParser/X86AsmParser.cpp b/lib/Target/X86/AsmParser/X86AsmParser.cpp index 39e58557d28..aa857f087d8 100644 --- a/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ b/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -923,19 +923,19 @@ struct X86Operand : public MCParsedAsmOperand { } bool isMemOffs8() const { - return Kind == Memory && !getMemSegReg() && !getMemBaseReg() && + return Kind == Memory && !getMemBaseReg() && !getMemIndexReg() && getMemScale() == 1 && (!Mem.Size || Mem.Size == 8); } bool isMemOffs16() const { - return Kind == Memory && !getMemSegReg() && !getMemBaseReg() && + return Kind == Memory && !getMemBaseReg() && !getMemIndexReg() && getMemScale() == 1 && (!Mem.Size || Mem.Size == 16); } bool isMemOffs32() const { - return Kind == Memory && !getMemSegReg() && !getMemBaseReg() && + return Kind == Memory && !getMemBaseReg() && !getMemIndexReg() && getMemScale() == 1 && (!Mem.Size || Mem.Size == 32); } bool isMemOffs64() const { - return Kind == Memory && !getMemSegReg() && !getMemBaseReg() && + return Kind == Memory && !getMemBaseReg() && !getMemIndexReg() && getMemScale() == 1 && (!Mem.Size || Mem.Size == 64); } @@ -1015,12 +1015,13 @@ struct X86Operand : public MCParsedAsmOperand { } void addMemOffsOperands(MCInst &Inst, unsigned N) const { - assert((N == 1) && "Invalid number of operands!"); + assert((N == 2) && "Invalid number of operands!"); // Add as immediates when possible. if (const MCConstantExpr *CE = dyn_cast(getMemDisp())) Inst.addOperand(MCOperand::CreateImm(CE->getValue())); else Inst.addOperand(MCOperand::CreateExpr(getMemDisp())); + Inst.addOperand(MCOperand::CreateReg(getMemSegReg())); } static X86Operand *CreateToken(StringRef Str, SMLoc Loc) { diff --git a/lib/Target/X86/Disassembler/X86Disassembler.cpp b/lib/Target/X86/Disassembler/X86Disassembler.cpp index 240d8ce9404..5ded46d8d56 100644 --- a/lib/Target/X86/Disassembler/X86Disassembler.cpp +++ b/lib/Target/X86/Disassembler/X86Disassembler.cpp @@ -207,6 +207,16 @@ static void tryAddingPcLoadReferenceComment(uint64_t Address, uint64_t Value, Dis->tryAddingPcLoadReferenceComment(Value, Address); } +static const uint8_t segmentRegnums[SEG_OVERRIDE_max] = { + 0, // SEG_OVERRIDE_NONE + X86::CS, + X86::SS, + X86::DS, + X86::ES, + X86::FS, + X86::GS +}; + /// translateImmediate - Appends an immediate operand to an MCInst. /// /// @param mcInst - The MCInst to append to. @@ -315,6 +325,13 @@ static void translateImmediate(MCInst &mcInst, uint64_t immediate, insn.immediateOffset, insn.immediateSize, mcInst, Dis)) mcInst.addOperand(MCOperand::CreateImm(immediate)); + + if (type == TYPE_MOFFS8 || type == TYPE_MOFFS16 || + type == TYPE_MOFFS32 || type == TYPE_MOFFS64) { + MCOperand segmentReg; + segmentReg = MCOperand::CreateReg(segmentRegnums[insn.segmentOverride]); + mcInst.addOperand(segmentReg); + } } /// translateRMRegister - Translates a register stored in the R/M field of the @@ -522,17 +539,7 @@ static bool translateRMMemory(MCInst &mcInst, InternalInstruction &insn, } displacement = MCOperand::CreateImm(insn.displacement); - - static const uint8_t segmentRegnums[SEG_OVERRIDE_max] = { - 0, // SEG_OVERRIDE_NONE - X86::CS, - X86::SS, - X86::DS, - X86::ES, - X86::FS, - X86::GS - }; - + segmentReg = MCOperand::CreateReg(segmentRegnums[insn.segmentOverride]); mcInst.addOperand(baseReg); diff --git a/lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp b/lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp index 8c2bb0f9e9f..11a9ada41e5 100644 --- a/lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp +++ b/lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp @@ -229,9 +229,16 @@ void X86ATTInstPrinter::printMemReference(const MCInst *MI, unsigned Op, void X86ATTInstPrinter::printMemOffset(const MCInst *MI, unsigned Op, raw_ostream &O) { const MCOperand &DispSpec = MI->getOperand(Op); + const MCOperand &SegReg = MI->getOperand(Op+1); O << markup("getOperand(Op); + const MCOperand &SegReg = MI->getOperand(Op+1); + + // If this has a segment register, print it. + if (SegReg.getReg()) { + printOperand(MI, Op+1, O); + O << ':'; + } O << '['; diff --git a/lib/Target/X86/MCTargetDesc/X86BaseInfo.h b/lib/Target/X86/MCTargetDesc/X86BaseInfo.h index 404a7e80e6c..b25a35e321c 100644 --- a/lib/Target/X86/MCTargetDesc/X86BaseInfo.h +++ b/lib/Target/X86/MCTargetDesc/X86BaseInfo.h @@ -255,6 +255,10 @@ namespace X86II { /// MRMSrcMem = 6, + /// RawFrmMemOffs - This form is for instructions that store an absolute + /// memory offset as an immediate with a possible segment override. + RawFrmMemOffs = 7, + /// MRM[0-7][rm] - These forms are used to represent instructions that use /// a Mod/RM byte, and use the middle field to hold extended opcode /// information. In the intel manual these are represented as /0, /1, ... @@ -607,6 +611,7 @@ namespace X86II { case X86II::MRMSrcReg: case X86II::RawFrmImm8: case X86II::RawFrmImm16: + case X86II::RawFrmMemOffs: return -1; case X86II::MRMDestMem: return 0; diff --git a/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp b/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp index 55a89329261..a48f979c0b4 100644 --- a/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp +++ b/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp @@ -158,9 +158,8 @@ public: const MCInst &MI, const MCInstrDesc &Desc, raw_ostream &OS) const; - void EmitSegmentOverridePrefix(uint64_t TSFlags, unsigned &CurByte, - int MemOperand, const MCInst &MI, - raw_ostream &OS) const; + void EmitSegmentOverridePrefix(unsigned &CurByte, unsigned SegOperand, + const MCInst &MI, raw_ostream &OS) const; void EmitOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, int MemOperand, const MCInst &MI, const MCInstrDesc &Desc, @@ -977,7 +976,8 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, } // Emit segment override opcode prefix as needed. - EmitSegmentOverridePrefix(TSFlags, CurByte, MemOperand, MI, OS); + if (MemOperand >= 0) + EmitSegmentOverridePrefix(CurByte, MemOperand+X86::AddrSegmentReg, MI, OS); if (!HasEVEX) { // VEX opcode prefix can have 2 or 3 bytes @@ -1134,15 +1134,12 @@ static unsigned DetermineREXPrefix(const MCInst &MI, uint64_t TSFlags, } /// EmitSegmentOverridePrefix - Emit segment override opcode prefix as needed -void X86MCCodeEmitter::EmitSegmentOverridePrefix(uint64_t TSFlags, - unsigned &CurByte, int MemOperand, - const MCInst &MI, - raw_ostream &OS) const { - if (MemOperand < 0) - return; // No memory operand - +void X86MCCodeEmitter::EmitSegmentOverridePrefix(unsigned &CurByte, + unsigned SegOperand, + const MCInst &MI, + raw_ostream &OS) const { // Check for explicit segment override on memory operand. - switch (MI.getOperand(MemOperand+X86::AddrSegmentReg).getReg()) { + switch (MI.getOperand(SegOperand).getReg()) { default: llvm_unreachable("Unknown segment register!"); case 0: break; case X86::CS: EmitByte(0x2E, CurByte, OS); break; @@ -1168,7 +1165,8 @@ void X86MCCodeEmitter::EmitOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, EmitByte(0xF0, CurByte, OS); // Emit segment override opcode prefix as needed. - EmitSegmentOverridePrefix(TSFlags, CurByte, MemOperand, MI, OS); + if (MemOperand >= 0) + EmitSegmentOverridePrefix(CurByte, MemOperand+X86::AddrSegmentReg, MI, OS); // Emit the repeat opcode prefix as needed. if ((TSFlags & X86II::Op0Mask) == X86II::REP) @@ -1337,6 +1335,15 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS, case X86II::RawFrm: EmitByte(BaseOpcode, CurByte, OS); break; + case X86II::RawFrmMemOffs: + // Emit segment override opcode prefix as needed. + EmitSegmentOverridePrefix(CurByte, 1, MI, OS); + EmitByte(BaseOpcode, CurByte, OS); + EmitImmediate(MI.getOperand(CurOp++), MI.getLoc(), + X86II::getSizeOfImm(TSFlags), getImmFixupKind(TSFlags), + CurByte, OS, Fixups); + ++CurOp; // skip segment operand + break; case X86II::RawFrmImm8: EmitByte(BaseOpcode, CurByte, OS); EmitImmediate(MI.getOperand(CurOp++), MI.getLoc(), diff --git a/lib/Target/X86/X86InstrFormats.td b/lib/Target/X86/X86InstrFormats.td index 3e27176602f..eed361958f6 100644 --- a/lib/Target/X86/X86InstrFormats.td +++ b/lib/Target/X86/X86InstrFormats.td @@ -21,7 +21,7 @@ class Format val> { def Pseudo : Format<0>; def RawFrm : Format<1>; def AddRegFrm : Format<2>; def MRMDestReg : Format<3>; def MRMDestMem : Format<4>; def MRMSrcReg : Format<5>; -def MRMSrcMem : Format<6>; +def MRMSrcMem : Format<6>; def RawFrmMemOffs : Format<7>; def MRM0r : Format<16>; def MRM1r : Format<17>; def MRM2r : Format<18>; def MRM3r : Format<19>; def MRM4r : Format<20>; def MRM5r : Format<21>; def MRM6r : Format<22>; def MRM7r : Format<23>; diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td index 1681ad7a5e8..1a5deabdc40 100644 --- a/lib/Target/X86/X86InstrInfo.td +++ b/lib/Target/X86/X86InstrInfo.td @@ -467,17 +467,21 @@ def X86MemOffs64AsmOperand : AsmOperandClass { } let OperandType = "OPERAND_MEMORY" in { -def offset8 : Operand { +def offset8 : Operand { let ParserMatchClass = X86MemOffs8AsmOperand; + let MIOperandInfo = (ops i64imm, i8imm); let PrintMethod = "printMemOffs8"; } -def offset16 : Operand { +def offset16 : Operand { let ParserMatchClass = X86MemOffs16AsmOperand; + let MIOperandInfo = (ops i64imm, i8imm); let PrintMethod = "printMemOffs16"; } -def offset32 : Operand { +def offset32 : Operand { let ParserMatchClass = X86MemOffs32AsmOperand; + let MIOperandInfo = (ops i64imm, i8imm); let PrintMethod = "printMemOffs32"; } -def offset64 : Operand { +def offset64 : Operand { let ParserMatchClass = X86MemOffs64AsmOperand; + let MIOperandInfo = (ops i64imm, i8imm); let PrintMethod = "printMemOffs64"; } } @@ -1146,44 +1150,44 @@ let hasSideEffects = 0 in { /// 32-bit offset from the segment base. These are only valid in x86-32 mode. let SchedRW = [WriteALU] in { let mayLoad = 1 in { -def MOV8o8a : Ii32 <0xA0, RawFrm, (outs), (ins offset8:$src), +def MOV8o8a : Ii32 <0xA0, RawFrmMemOffs, (outs), (ins offset8:$src), "mov{b}\t{$src, %al|al, $src}", [], IIC_MOV_MEM>, Requires<[In32BitMode]>; -def MOV16o16a : Ii32 <0xA1, RawFrm, (outs), (ins offset16:$src), +def MOV16o16a : Ii32 <0xA1, RawFrmMemOffs, (outs), (ins offset16:$src), "mov{w}\t{$src, %ax|ax, $src}", [], IIC_MOV_MEM>, OpSize, Requires<[In32BitMode]>; -def MOV32o32a : Ii32 <0xA1, RawFrm, (outs), (ins offset32:$src), +def MOV32o32a : Ii32 <0xA1, RawFrmMemOffs, (outs), (ins offset32:$src), "mov{l}\t{$src, %eax|eax, $src}", [], IIC_MOV_MEM>, OpSize16, Requires<[In32BitMode]>; -def MOV8o8a_16 : Ii16 <0xA0, RawFrm, (outs), (ins offset8:$src), +def MOV8o8a_16 : Ii16 <0xA0, RawFrmMemOffs, (outs), (ins offset8:$src), "mov{b}\t{$src, %al|al, $src}", [], IIC_MOV_MEM>, AdSize, Requires<[In16BitMode]>; -def MOV16o16a_16 : Ii16 <0xA1, RawFrm, (outs), (ins offset16:$src), +def MOV16o16a_16 : Ii16 <0xA1, RawFrmMemOffs, (outs), (ins offset16:$src), "mov{w}\t{$src, %ax|ax, $src}", [], IIC_MOV_MEM>, OpSize, AdSize, Requires<[In16BitMode]>; -def MOV32o32a_16 : Ii16 <0xA1, RawFrm, (outs), (ins offset32:$src), +def MOV32o32a_16 : Ii16 <0xA1, RawFrmMemOffs, (outs), (ins offset32:$src), "mov{l}\t{$src, %eax|eax, $src}", [], IIC_MOV_MEM>, AdSize, OpSize16, Requires<[In16BitMode]>; } let mayStore = 1 in { -def MOV8ao8 : Ii32 <0xA2, RawFrm, (outs offset8:$dst), (ins), +def MOV8ao8 : Ii32 <0xA2, RawFrmMemOffs, (outs offset8:$dst), (ins), "mov{b}\t{%al, $dst|$dst, al}", [], IIC_MOV_MEM>, Requires<[In32BitMode]>; -def MOV16ao16 : Ii32 <0xA3, RawFrm, (outs offset16:$dst), (ins), +def MOV16ao16 : Ii32 <0xA3, RawFrmMemOffs, (outs offset16:$dst), (ins), "mov{w}\t{%ax, $dst|$dst, ax}", [], IIC_MOV_MEM>, OpSize, Requires<[In32BitMode]>; -def MOV32ao32 : Ii32 <0xA3, RawFrm, (outs offset32:$dst), (ins), +def MOV32ao32 : Ii32 <0xA3, RawFrmMemOffs, (outs offset32:$dst), (ins), "mov{l}\t{%eax, $dst|$dst, eax}", [], IIC_MOV_MEM>, OpSize16, Requires<[In32BitMode]>; -def MOV8ao8_16 : Ii16 <0xA2, RawFrm, (outs offset8:$dst), (ins), +def MOV8ao8_16 : Ii16 <0xA2, RawFrmMemOffs, (outs offset8:$dst), (ins), "mov{b}\t{%al, $dst|$dst, al}", [], IIC_MOV_MEM>, AdSize, Requires<[In16BitMode]>; -def MOV16ao16_16 : Ii16 <0xA3, RawFrm, (outs offset16:$dst), (ins), +def MOV16ao16_16 : Ii16 <0xA3, RawFrmMemOffs, (outs offset16:$dst), (ins), "mov{w}\t{%ax, $dst|$dst, ax}", [], IIC_MOV_MEM>, OpSize, AdSize, Requires<[In16BitMode]>; -def MOV32ao32_16 : Ii16 <0xA3, RawFrm, (outs offset32:$dst), (ins), +def MOV32ao32_16 : Ii16 <0xA3, RawFrmMemOffs, (outs offset32:$dst), (ins), "mov{l}\t{%eax, $dst|$dst, eax}", [], IIC_MOV_MEM>, OpSize16, AdSize, Requires<[In16BitMode]>; } @@ -1192,31 +1196,31 @@ def MOV32ao32_16 : Ii16 <0xA3, RawFrm, (outs offset32:$dst), (ins), // These forms all have full 64-bit absolute addresses in their instructions // and use the movabs mnemonic to indicate this specific form. let mayLoad = 1 in { -def MOV64o8a : RIi64_NOREX<0xA0, RawFrm, (outs), (ins offset8:$src), +def MOV64o8a : RIi64_NOREX<0xA0, RawFrmMemOffs, (outs), (ins offset8:$src), "movabs{b}\t{$src, %al|al, $src}", []>, Requires<[In64BitMode]>; -def MOV64o16a : RIi64_NOREX<0xA1, RawFrm, (outs), (ins offset16:$src), +def MOV64o16a : RIi64_NOREX<0xA1, RawFrmMemOffs, (outs), (ins offset16:$src), "movabs{w}\t{$src, %ax|ax, $src}", []>, OpSize, Requires<[In64BitMode]>; -def MOV64o32a : RIi64_NOREX<0xA1, RawFrm, (outs), (ins offset32:$src), +def MOV64o32a : RIi64_NOREX<0xA1, RawFrmMemOffs, (outs), (ins offset32:$src), "movabs{l}\t{$src, %eax|eax, $src}", []>, Requires<[In64BitMode]>; -def MOV64o64a : RIi64<0xA1, RawFrm, (outs), (ins offset64:$src), +def MOV64o64a : RIi64<0xA1, RawFrmMemOffs, (outs), (ins offset64:$src), "movabs{q}\t{$src, %rax|rax, $src}", []>, Requires<[In64BitMode]>; } let mayStore = 1 in { -def MOV64ao8 : RIi64_NOREX<0xA2, RawFrm, (outs offset8:$dst), (ins), +def MOV64ao8 : RIi64_NOREX<0xA2, RawFrmMemOffs, (outs offset8:$dst), (ins), "movabs{b}\t{%al, $dst|$dst, al}", []>, Requires<[In64BitMode]>; -def MOV64ao16 : RIi64_NOREX<0xA3, RawFrm, (outs offset16:$dst), (ins), +def MOV64ao16 : RIi64_NOREX<0xA3, RawFrmMemOffs, (outs offset16:$dst), (ins), "movabs{w}\t{%ax, $dst|$dst, ax}", []>, OpSize, Requires<[In64BitMode]>; -def MOV64ao32 : RIi64_NOREX<0xA3, RawFrm, (outs offset32:$dst), (ins), +def MOV64ao32 : RIi64_NOREX<0xA3, RawFrmMemOffs, (outs offset32:$dst), (ins), "movabs{l}\t{%eax, $dst|$dst, eax}", []>, Requires<[In64BitMode]>; -def MOV64ao64 : RIi64<0xA3, RawFrm, (outs offset64:$dst), (ins), +def MOV64ao64 : RIi64<0xA3, RawFrmMemOffs, (outs offset64:$dst), (ins), "movabs{q}\t{%rax, $dst|$dst, rax}", []>, Requires<[In64BitMode]>; } diff --git a/test/MC/Disassembler/X86/x86-32.txt b/test/MC/Disassembler/X86/x86-32.txt index b6a62c4f697..e906c1ae793 100644 --- a/test/MC/Disassembler/X86/x86-32.txt +++ b/test/MC/Disassembler/X86/x86-32.txt @@ -696,3 +696,6 @@ # CHECK: vmovq %xmm0, %xmm0 0xc5 0xfa 0x7e 0xc0 + +# CHECK: movl %fs:0, %eax +0x64 0xa1 0x00 0x00 0x00 0x00 diff --git a/test/MC/X86/x86-16.s b/test/MC/X86/x86-16.s index 1910f46378f..9cb80095227 100644 --- a/test/MC/X86/x86-16.s +++ b/test/MC/X86/x86-16.s @@ -330,8 +330,7 @@ cmovnae %bx,%bx // CHECK: encoding: [0x9b] fwait -// CHECK: [0x65,0x66,0x8b,0x06,0x7c,0x00] -// FIXME: This is a correct bug poor encoding: Use 65 66 a1 7c 00 +// CHECK: [0x66,0x65,0xa1,0x7c,0x00] movl %gs:124, %eax // CHECK: pusha diff --git a/test/MC/X86/x86-32.s b/test/MC/X86/x86-32.s index 1ce2d498964..140c05af6bc 100644 --- a/test/MC/X86/x86-32.s +++ b/test/MC/X86/x86-32.s @@ -438,10 +438,12 @@ cmovnae %bx,%bx fwait // rdar://7873482 -// CHECK: [0x65,0x8b,0x05,0x7c,0x00,0x00,0x00] -// FIXME: This is a correct bug poor encoding: Use 65 a1 7c 00 00 00 +// CHECK: [0x65,0xa1,0x7c,0x00,0x00,0x00] movl %gs:124, %eax +// CHECK: [0x65,0xa3,0x7c,0x00,0x00,0x00] + movl %eax, %gs:124 + // CHECK: pushal // CHECK: encoding: [0x60] pusha diff --git a/utils/TableGen/X86RecognizableInstr.cpp b/utils/TableGen/X86RecognizableInstr.cpp index 986fd8b8f3d..019610e1471 100644 --- a/utils/TableGen/X86RecognizableInstr.cpp +++ b/utils/TableGen/X86RecognizableInstr.cpp @@ -59,11 +59,11 @@ namespace X86Local { MRMDestMem = 4, MRMSrcReg = 5, MRMSrcMem = 6, + RawFrmMemOffs = 7, MRM0r = 16, MRM1r = 17, MRM2r = 18, MRM3r = 19, MRM4r = 20, MRM5r = 21, MRM6r = 22, MRM7r = 23, MRM0m = 24, MRM1m = 25, MRM2m = 26, MRM3m = 27, MRM4m = 28, MRM5m = 29, MRM6m = 30, MRM7m = 31, - MRMInitReg = 32, RawFrmImm8 = 43, RawFrmImm16 = 44, #define MAP(from, to) MRM_##from = to, @@ -631,6 +631,7 @@ void RecognizableInstr::emitInstructionSpecifier() { unsigned physicalOperandIndex = 0; switch (Form) { + default: llvm_unreachable("Unhandled form"); case X86Local::RawFrm: // Operand 1 (optional) is an address or immediate. // Operand 2 (optional) is an immediate. @@ -639,6 +640,10 @@ void RecognizableInstr::emitInstructionSpecifier() { HANDLE_OPTIONAL(relocation) HANDLE_OPTIONAL(immediate) break; + case X86Local::RawFrmMemOffs: + // Operand 1 is an address. + HANDLE_OPERAND(relocation); + break; case X86Local::AddRegFrm: // Operand 1 is added to the opcode. // Operand 2 (optional) is an address. @@ -840,7 +845,30 @@ void RecognizableInstr::emitInstructionSpecifier() { HANDLE_OPERAND(relocation) } break; - case X86Local::MRMInitReg: + case X86Local::MRM_C1: + case X86Local::MRM_C2: + case X86Local::MRM_C3: + case X86Local::MRM_C4: + case X86Local::MRM_C8: + case X86Local::MRM_C9: + case X86Local::MRM_CA: + case X86Local::MRM_CB: + case X86Local::MRM_E8: + case X86Local::MRM_F0: + case X86Local::MRM_F9: + case X86Local::MRM_D0: + case X86Local::MRM_D1: + case X86Local::MRM_D4: + case X86Local::MRM_D5: + case X86Local::MRM_D6: + case X86Local::MRM_D8: + case X86Local::MRM_D9: + case X86Local::MRM_DA: + case X86Local::MRM_DB: + case X86Local::MRM_DC: + case X86Local::MRM_DD: + case X86Local::MRM_DE: + case X86Local::MRM_DF: // Ignored. break; }