From 70ff3e91f75bd89ade80242f4bab13226e7831bc Mon Sep 17 00:00:00 2001 From: Bob Wilson Date: Mon, 10 Feb 2014 05:28:30 +0000 Subject: Revert r201059 and r201060. r201059 appears to cause a crash in a bootstrapped build of clang. Craig isn't available to look at it right now, so I'm reverting it while he investigates. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@201064 91177308-0d34-0410-b5e6-96231b3b80d8 --- utils/TableGen/X86RecognizableInstr.cpp | 339 ++++++++++++++++++++++++++++---- 1 file changed, 299 insertions(+), 40 deletions(-) (limited to 'utils') diff --git a/utils/TableGen/X86RecognizableInstr.cpp b/utils/TableGen/X86RecognizableInstr.cpp index 48d8fdc4d9..62aab5b68a 100644 --- a/utils/TableGen/X86RecognizableInstr.cpp +++ b/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: + opcodeType = TWOBYTE; + + switch (Opcode) { + default: + if (needsModRMForDecode(Form)) + filter = new ModFilter(isRegFormat(Form)); + else + filter = new DumbFilter(); + break; +#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: - 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; - } - - switch (Form) { + opcodeType = XOP9_MAP; + switch (Opcode) { default: - filter = new DumbFilter(); - break; - case X86Local::MRMDestReg: case X86Local::MRMDestMem: - case X86Local::MRMSrcReg: case X86Local::MRMSrcMem: - case X86Local::MRMXr: case X86Local::MRMXm: - filter = new ModFilter(isRegFormat(Form)); - 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); + if (needsModRMForDecode(Form)) + filter = new ModFilter(isRegFormat(Form)); + else + filter = new DumbFilter(); 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); +#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; - 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 && -- cgit v1.2.3