diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h b/llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h index 905d4e0db5d2..f35cc9d7bb12 100644 --- a/llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h +++ b/llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h @@ -272,10 +272,6 @@ namespace X86II { /// destination index register DI/ESI/RDI. RawFrmDstSrc = 10, - /// MRMX[rm] - The forms are used to represent instructions that use a - /// Mod/RM byte, and don't use the middle field for anything. - MRMXr = 14, MRMXm = 15, - /// 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, ... @@ -678,13 +674,11 @@ namespace X86II { // Opcode == X86::LEA16r || Opcode == X86::LEA32r) return FirstMemOp; } - case X86II::MRMXr: case X86II::MRM0r: case X86II::MRM1r: case X86II::MRM2r: case X86II::MRM3r: case X86II::MRM4r: case X86II::MRM5r: case X86II::MRM6r: case X86II::MRM7r: return -1; - case X86II::MRMXm: case X86II::MRM0m: case X86II::MRM1m: case X86II::MRM2m: case X86II::MRM3m: case X86II::MRM4m: case X86II::MRM5m: diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp index 5a4111044ea7..a76eecaaee6a 100644 --- a/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp +++ b/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp @@ -1426,35 +1426,28 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS, break; } - case X86II::MRMXr: case X86II::MRM0r: case X86II::MRM1r: case X86II::MRM2r: case X86II::MRM3r: case X86II::MRM4r: case X86II::MRM5r: - case X86II::MRM6r: case X86II::MRM7r: { + case X86II::MRM6r: case X86II::MRM7r: if (HasVEX_4V) // Skip the register dst (which is encoded in VEX_VVVV). ++CurOp; EmitByte(BaseOpcode, CurByte, OS); - uint64_t Form = TSFlags & X86II::FormMask; EmitRegModRMByte(MI.getOperand(CurOp++), - (Form == X86II::MRMXr) ? 0 : Form-X86II::MRM0r, + (TSFlags & X86II::FormMask)-X86II::MRM0r, CurByte, OS); break; - } - - case X86II::MRMXm: case X86II::MRM0m: case X86II::MRM1m: case X86II::MRM2m: case X86II::MRM3m: case X86II::MRM4m: case X86II::MRM5m: - case X86II::MRM6m: case X86II::MRM7m: { + case X86II::MRM6m: case X86II::MRM7m: if (HasVEX_4V) // Skip the register dst (which is encoded in VEX_VVVV). ++CurOp; EmitByte(BaseOpcode, CurByte, OS); - uint64_t Form = TSFlags & X86II::FormMask; - EmitMemModRMByte(MI, CurOp, (Form == X86II::MRMXm) ? 0 : Form-X86II::MRM0m, + EmitMemModRMByte(MI, CurOp, (TSFlags & X86II::FormMask)-X86II::MRM0m, TSFlags, CurByte, OS, Fixups, STI); CurOp += X86::AddrNumOperands; break; - } case X86II::MRM_C1: case X86II::MRM_C2: case X86II::MRM_C3: case X86II::MRM_C4: case X86II::MRM_C8: case X86II::MRM_C9: case X86II::MRM_CA: case X86II::MRM_CB: case X86II::MRM_D0: diff --git a/llvm/lib/Target/X86/X86CodeEmitter.cpp b/llvm/lib/Target/X86/X86CodeEmitter.cpp index 378f24d9fe8c..579bf9b3e6d6 100644 --- a/llvm/lib/Target/X86/X86CodeEmitter.cpp +++ b/llvm/lib/Target/X86/X86CodeEmitter.cpp @@ -1295,7 +1295,6 @@ void Emitter::emitInstruction(MachineInstr &MI, break; } - case X86II::MRMXr: case X86II::MRM0r: case X86II::MRM1r: case X86II::MRM2r: case X86II::MRM3r: case X86II::MRM4r: case X86II::MRM5r: @@ -1303,9 +1302,8 @@ void Emitter::emitInstruction(MachineInstr &MI, if (HasVEX_4V) // Skip the register dst (which is encoded in VEX_VVVV). ++CurOp; MCE.emitByte(BaseOpcode); - uint64_t Form = (Desc->TSFlags & X86II::FormMask); emitRegModRMByte(MI.getOperand(CurOp++).getReg(), - (Form == X86II::MRMXr) ? 0 : Form-X86II::MRM0r); + (Desc->TSFlags & X86II::FormMask)-X86II::MRM0r); if (CurOp == NumOps) break; @@ -1334,7 +1332,6 @@ void Emitter::emitInstruction(MachineInstr &MI, break; } - case X86II::MRMXm: case X86II::MRM0m: case X86II::MRM1m: case X86II::MRM2m: case X86II::MRM3m: case X86II::MRM4m: case X86II::MRM5m: @@ -1346,8 +1343,7 @@ void Emitter::emitInstruction(MachineInstr &MI, X86II::getSizeOfImm(Desc->TSFlags) : 4) : 0; MCE.emitByte(BaseOpcode); - uint64_t Form = (Desc->TSFlags & X86II::FormMask); - emitMemModRMByte(MI, CurOp, (Form==X86II::MRMXm) ? 0 : Form - X86II::MRM0m, + emitMemModRMByte(MI, CurOp, (Desc->TSFlags & X86II::FormMask)-X86II::MRM0m, PCAdj); CurOp += X86::AddrNumOperands; diff --git a/llvm/lib/Target/X86/X86InstrCMovSetCC.td b/llvm/lib/Target/X86/X86InstrCMovSetCC.td index 315f21308c0d..9a8ac630b6f7 100644 --- a/llvm/lib/Target/X86/X86InstrCMovSetCC.td +++ b/llvm/lib/Target/X86/X86InstrCMovSetCC.td @@ -82,11 +82,11 @@ defm CMOVG : CMOV<0x4F, "cmovg" , X86_COND_G>; // SetCC instructions. multiclass SETCC opc, string Mnemonic, PatLeaf OpNode> { let Uses = [EFLAGS] in { - def r : I, TB, Sched<[WriteALU]>; - def m : I, TB, Sched<[WriteALU, WriteStore]>; diff --git a/llvm/lib/Target/X86/X86InstrFormats.td b/llvm/lib/Target/X86/X86InstrFormats.td index bff583ac5063..a834438ffcc3 100644 --- a/llvm/lib/Target/X86/X86InstrFormats.td +++ b/llvm/lib/Target/X86/X86InstrFormats.td @@ -24,7 +24,6 @@ def MRMDestMem : Format<4>; def MRMSrcReg : Format<5>; def MRMSrcMem : Format<6>; def RawFrmMemOffs : Format<7>; def RawFrmSrc : Format<8>; def RawFrmDst : Format<9>; def RawFrmDstSrc: Format<10>; -def MRMXr : Format<14>; def MRMXm : Format<15>; 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/llvm/lib/Target/X86/X86InstrInfo.td b/llvm/lib/Target/X86/X86InstrInfo.td index 776bd8145a73..e1fc2ace8324 100644 --- a/llvm/lib/Target/X86/X86InstrInfo.td +++ b/llvm/lib/Target/X86/X86InstrInfo.td @@ -928,9 +928,9 @@ def trunc_su : PatFrag<(ops node:$src), (trunc node:$src), [{ // Nop let neverHasSideEffects = 1, SchedRW = [WriteZero] in { def NOOP : I<0x90, RawFrm, (outs), (ins), "nop", [], IIC_NOP>; - def NOOPW : I<0x1f, MRMXm, (outs), (ins i16mem:$zero), + def NOOPW : I<0x1f, MRM0m, (outs), (ins i16mem:$zero), "nop{w}\t$zero", [], IIC_NOP>, TB, OpSize16; - def NOOPL : I<0x1f, MRMXm, (outs), (ins i32mem:$zero), + def NOOPL : I<0x1f, MRM0m, (outs), (ins i32mem:$zero), "nop{l}\t$zero", [], IIC_NOP>, TB, OpSize32; } diff --git a/llvm/lib/Target/X86/X86InstrSSE.td b/llvm/lib/Target/X86/X86InstrSSE.td index 431d973026bd..ea91b5b10423 100644 --- a/llvm/lib/Target/X86/X86InstrSSE.td +++ b/llvm/lib/Target/X86/X86InstrSSE.td @@ -7677,7 +7677,7 @@ defm : pclmul_alias<"lqlq", 0x00>; let Predicates = [HasSSE4A] in { let Constraints = "$src = $dst" in { -def EXTRQI : Ii8<0x78, MRMXr, (outs VR128:$dst), +def EXTRQI : Ii8<0x78, MRM0r, (outs VR128:$dst), (ins VR128:$src, i8imm:$len, i8imm:$idx), "extrq\t{$idx, $len, $src|$src, $len, $idx}", [(set VR128:$dst, (int_x86_sse4a_extrqi VR128:$src, imm:$len, diff --git a/llvm/utils/TableGen/X86RecognizableInstr.cpp b/llvm/utils/TableGen/X86RecognizableInstr.cpp index 48d8fdc4d9ab..62aab5b68ae9 100644 --- a/llvm/utils/TableGen/X86RecognizableInstr.cpp +++ b/llvm/utils/TableGen/X86RecognizableInstr.cpp @@ -63,7 +63,6 @@ namespace X86Local { RawFrmSrc = 8, RawFrmDst = 9, RawFrmDstSrc = 10, - MRMXr = 14, MRMXm = 15, MRM0r = 16, MRM1r = 17, MRM2r = 18, MRM3r = 19, MRM4r = 20, MRM5r = 21, MRM6r = 22, MRM7r = 23, MRM0m = 24, MRM1m = 25, MRM2m = 26, MRM3m = 27, @@ -96,8 +95,80 @@ namespace X86Local { }; } +// If rows are added to the opcode extension tables, then corresponding entries +// must be added here. +// +// If the row corresponds to a single byte (i.e., 8f), then add an entry for +// that byte to ONE_BYTE_EXTENSION_TABLES. +// +// If the row corresponds to two bytes where the first is 0f, add an entry for +// the second byte to TWO_BYTE_EXTENSION_TABLES. +// +// If the row corresponds to some other set of bytes, you will need to modify +// the code in RecognizableInstr::emitDecodePath() as well, and add new prefixes +// to the X86 TD files, except in two cases: if the first two bytes of such a +// new combination are 0f 38 or 0f 3a, you just have to add maps called +// THREE_BYTE_38_EXTENSION_TABLES and THREE_BYTE_3A_EXTENSION_TABLES and add a +// switch(Opcode) just below the case X86Local::T8: or case X86Local::TA: line +// in RecognizableInstr::emitDecodePath(). + +#define ONE_BYTE_EXTENSION_TABLES \ + EXTENSION_TABLE(80) \ + EXTENSION_TABLE(81) \ + EXTENSION_TABLE(82) \ + EXTENSION_TABLE(83) \ + EXTENSION_TABLE(8f) \ + EXTENSION_TABLE(c0) \ + EXTENSION_TABLE(c1) \ + EXTENSION_TABLE(c6) \ + EXTENSION_TABLE(c7) \ + EXTENSION_TABLE(d0) \ + EXTENSION_TABLE(d1) \ + EXTENSION_TABLE(d2) \ + EXTENSION_TABLE(d3) \ + EXTENSION_TABLE(f6) \ + EXTENSION_TABLE(f7) \ + EXTENSION_TABLE(fe) \ + EXTENSION_TABLE(ff) + +#define TWO_BYTE_EXTENSION_TABLES \ + EXTENSION_TABLE(00) \ + EXTENSION_TABLE(01) \ + EXTENSION_TABLE(0d) \ + EXTENSION_TABLE(18) \ + EXTENSION_TABLE(71) \ + EXTENSION_TABLE(72) \ + EXTENSION_TABLE(73) \ + EXTENSION_TABLE(ae) \ + EXTENSION_TABLE(ba) \ + EXTENSION_TABLE(c7) + +#define THREE_BYTE_38_EXTENSION_TABLES \ + EXTENSION_TABLE(F3) + +#define XOP9_MAP_EXTENSION_TABLES \ + EXTENSION_TABLE(01) \ + EXTENSION_TABLE(02) + using namespace X86Disassembler; +/// needsModRMForDecode - Indicates whether a particular instruction requires a +/// ModR/M byte for the instruction to be properly decoded. For example, a +/// MRMDestReg instruction needs the Mod field in the ModR/M byte to be set to +/// 0b11. +/// +/// @param form - The form of the instruction. +/// @return - true if the form implies that a ModR/M byte is required, false +/// otherwise. +static bool needsModRMForDecode(uint8_t form) { + return (form == X86Local::MRMDestReg || + form == X86Local::MRMDestMem || + form == X86Local::MRMSrcReg || + form == X86Local::MRMSrcMem || + (form >= X86Local::MRM0r && form <= X86Local::MRM7r) || + (form >= X86Local::MRM0m && form <= X86Local::MRM7m)); +} + /// isRegFormat - Indicates whether a particular form requires the Mod field of /// the ModR/M byte to be 0b11. /// @@ -107,7 +178,6 @@ using namespace X86Disassembler; static bool isRegFormat(uint8_t form) { return (form == X86Local::MRMDestReg || form == X86Local::MRMSrcReg || - form == X86Local::MRMXr || (form >= X86Local::MRM0r && form <= X86Local::MRM7r)); } @@ -671,7 +741,6 @@ void RecognizableInstr::emitInstructionSpecifier() { HANDLE_OPTIONAL(immediate) HANDLE_OPTIONAL(immediate) // above might be a register in 7:4 break; - case X86Local::MRMXr: case X86Local::MRM0r: case X86Local::MRM1r: case X86Local::MRM2r: @@ -698,7 +767,6 @@ void RecognizableInstr::emitInstructionSpecifier() { HANDLE_OPTIONAL(relocation) HANDLE_OPTIONAL(immediate) break; - case X86Local::MRMXm: case X86Local::MRM0m: case X86Local::MRM1m: case X86Local::MRM2m: @@ -795,52 +863,169 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const { switch (OpMap) { default: llvm_unreachable("Invalid map!"); - case X86Local::OB: + // Extended two-byte opcodes can start with 66 0f, f2 0f, f3 0f, or 0f case X86Local::TB: - case X86Local::T8: - case X86Local::TA: - case X86Local::A6: - case X86Local::A7: - case X86Local::XOP8: - case X86Local::XOP9: - case X86Local::XOPA: - switch (OpMap) { - default: llvm_unreachable("Unexpected map!"); - case X86Local::OB: opcodeType = ONEBYTE; break; - case X86Local::TB: opcodeType = TWOBYTE; break; - case X86Local::T8: opcodeType = THREEBYTE_38; break; - case X86Local::TA: opcodeType = THREEBYTE_3A; break; - case X86Local::A6: opcodeType = THREEBYTE_A6; break; - case X86Local::A7: opcodeType = THREEBYTE_A7; break; - case X86Local::XOP8: opcodeType = XOP8_MAP; break; - case X86Local::XOP9: opcodeType = XOP9_MAP; break; - case X86Local::XOPA: opcodeType = XOPA_MAP; break; - } + opcodeType = TWOBYTE; - switch (Form) { + switch (Opcode) { default: - filter = new DumbFilter(); + if (needsModRMForDecode(Form)) + filter = new ModFilter(isRegFormat(Form)); + else + filter = new DumbFilter(); break; - case X86Local::MRMDestReg: case X86Local::MRMDestMem: - case X86Local::MRMSrcReg: case X86Local::MRMSrcMem: - case X86Local::MRMXr: case X86Local::MRMXm: +#define EXTENSION_TABLE(n) case 0x##n: + TWO_BYTE_EXTENSION_TABLES +#undef EXTENSION_TABLE + switch (Form) { + default: + llvm_unreachable("Unhandled two-byte extended opcode"); + case X86Local::MRM0r: + case X86Local::MRM1r: + case X86Local::MRM2r: + case X86Local::MRM3r: + case X86Local::MRM4r: + case X86Local::MRM5r: + case X86Local::MRM6r: + case X86Local::MRM7r: + filter = new ExtendedFilter(true, Form - X86Local::MRM0r); + break; + case X86Local::MRM0m: + case X86Local::MRM1m: + case X86Local::MRM2m: + case X86Local::MRM3m: + case X86Local::MRM4m: + case X86Local::MRM5m: + case X86Local::MRM6m: + case X86Local::MRM7m: + filter = new ExtendedFilter(false, Form - X86Local::MRM0m); + break; + MRM_MAPPING + } // switch (Form) + break; + } // switch (Opcode) + opcodeToSet = Opcode; + break; + case X86Local::T8: + opcodeType = THREEBYTE_38; + switch (Opcode) { + default: + if (needsModRMForDecode(Form)) + filter = new ModFilter(isRegFormat(Form)); + else + filter = new DumbFilter(); + break; +#define EXTENSION_TABLE(n) case 0x##n: + THREE_BYTE_38_EXTENSION_TABLES +#undef EXTENSION_TABLE + switch (Form) { + default: + llvm_unreachable("Unhandled two-byte extended opcode"); + case X86Local::MRM0r: + case X86Local::MRM1r: + case X86Local::MRM2r: + case X86Local::MRM3r: + case X86Local::MRM4r: + case X86Local::MRM5r: + case X86Local::MRM6r: + case X86Local::MRM7r: + filter = new ExtendedFilter(true, Form - X86Local::MRM0r); + break; + case X86Local::MRM0m: + case X86Local::MRM1m: + case X86Local::MRM2m: + case X86Local::MRM3m: + case X86Local::MRM4m: + case X86Local::MRM5m: + case X86Local::MRM6m: + case X86Local::MRM7m: + filter = new ExtendedFilter(false, Form - X86Local::MRM0m); + break; + MRM_MAPPING + } // switch (Form) + break; + } // switch (Opcode) + opcodeToSet = Opcode; + break; + case X86Local::TA: + opcodeType = THREEBYTE_3A; + if (needsModRMForDecode(Form)) filter = new ModFilter(isRegFormat(Form)); + else + filter = new DumbFilter(); + opcodeToSet = Opcode; + break; + case X86Local::A6: + opcodeType = THREEBYTE_A6; + if (needsModRMForDecode(Form)) + filter = new ModFilter(isRegFormat(Form)); + else + filter = new DumbFilter(); + opcodeToSet = Opcode; + break; + case X86Local::A7: + opcodeType = THREEBYTE_A7; + if (needsModRMForDecode(Form)) + filter = new ModFilter(isRegFormat(Form)); + else + filter = new DumbFilter(); + opcodeToSet = Opcode; + break; + case X86Local::XOP8: + opcodeType = XOP8_MAP; + if (needsModRMForDecode(Form)) + filter = new ModFilter(isRegFormat(Form)); + else + filter = new DumbFilter(); + opcodeToSet = Opcode; + break; + case X86Local::XOP9: + opcodeType = XOP9_MAP; + switch (Opcode) { + default: + if (needsModRMForDecode(Form)) + filter = new ModFilter(isRegFormat(Form)); + else + filter = new DumbFilter(); break; - case X86Local::MRM0r: case X86Local::MRM1r: - case X86Local::MRM2r: case X86Local::MRM3r: - case X86Local::MRM4r: case X86Local::MRM5r: - case X86Local::MRM6r: case X86Local::MRM7r: - filter = new ExtendedFilter(true, Form - X86Local::MRM0r); +#define EXTENSION_TABLE(n) case 0x##n: + XOP9_MAP_EXTENSION_TABLES +#undef EXTENSION_TABLE + switch (Form) { + default: + llvm_unreachable("Unhandled XOP9 extended opcode"); + case X86Local::MRM0r: + case X86Local::MRM1r: + case X86Local::MRM2r: + case X86Local::MRM3r: + case X86Local::MRM4r: + case X86Local::MRM5r: + case X86Local::MRM6r: + case X86Local::MRM7r: + filter = new ExtendedFilter(true, Form - X86Local::MRM0r); + break; + case X86Local::MRM0m: + case X86Local::MRM1m: + case X86Local::MRM2m: + case X86Local::MRM3m: + case X86Local::MRM4m: + case X86Local::MRM5m: + case X86Local::MRM6m: + case X86Local::MRM7m: + filter = new ExtendedFilter(false, Form - X86Local::MRM0m); + break; + MRM_MAPPING + } // switch (Form) break; - case X86Local::MRM0m: case X86Local::MRM1m: - case X86Local::MRM2m: case X86Local::MRM3m: - case X86Local::MRM4m: case X86Local::MRM5m: - case X86Local::MRM6m: case X86Local::MRM7m: - filter = new ExtendedFilter(false, Form - X86Local::MRM0m); - break; - MRM_MAPPING - } // switch (Form) - + } // switch (Opcode) + opcodeToSet = Opcode; + break; + case X86Local::XOPA: + opcodeType = XOPA_MAP; + if (needsModRMForDecode(Form)) + filter = new ModFilter(isRegFormat(Form)); + else + filter = new DumbFilter(); opcodeToSet = Opcode; break; case X86Local::D8: @@ -857,6 +1042,80 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const { filter = new ExactFilter(Opcode); opcodeToSet = 0xd8 + (OpMap - X86Local::D8); break; + case X86Local::OB: + opcodeType = ONEBYTE; + switch (Opcode) { +#define EXTENSION_TABLE(n) case 0x##n: + ONE_BYTE_EXTENSION_TABLES +#undef EXTENSION_TABLE + switch (Form) { + default: + llvm_unreachable("Fell through the cracks of a single-byte " + "extended opcode"); + case X86Local::MRM0r: + case X86Local::MRM1r: + case X86Local::MRM2r: + case X86Local::MRM3r: + case X86Local::MRM4r: + case X86Local::MRM5r: + case X86Local::MRM6r: + case X86Local::MRM7r: + filter = new ExtendedFilter(true, Form - X86Local::MRM0r); + break; + case X86Local::MRM0m: + case X86Local::MRM1m: + case X86Local::MRM2m: + case X86Local::MRM3m: + case X86Local::MRM4m: + case X86Local::MRM5m: + case X86Local::MRM6m: + case X86Local::MRM7m: + filter = new ExtendedFilter(false, Form - X86Local::MRM0m); + break; + MRM_MAPPING + } // switch (Form) + break; + case 0xd8: + case 0xd9: + case 0xda: + case 0xdb: + case 0xdc: + case 0xdd: + case 0xde: + case 0xdf: + switch (Form) { + default: + llvm_unreachable("Unhandled escape opcode form"); + case X86Local::MRM0r: + case X86Local::MRM1r: + case X86Local::MRM2r: + case X86Local::MRM3r: + case X86Local::MRM4r: + case X86Local::MRM5r: + case X86Local::MRM6r: + case X86Local::MRM7r: + filter = new ExtendedFilter(true, Form - X86Local::MRM0r); + break; + case X86Local::MRM0m: + case X86Local::MRM1m: + case X86Local::MRM2m: + case X86Local::MRM3m: + case X86Local::MRM4m: + case X86Local::MRM5m: + case X86Local::MRM6m: + case X86Local::MRM7m: + filter = new ExtendedFilter(false, Form - X86Local::MRM0m); + break; + } // switch (Form) + break; + default: + if (needsModRMForDecode(Form)) + filter = new ModFilter(isRegFormat(Form)); + else + filter = new DumbFilter(); + break; + } // switch (Opcode) + opcodeToSet = Opcode; } // switch (OpMap) assert(opcodeType != (OpcodeType)-1 &&