X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;ds=inline;f=utils%2FTableGen%2FX86RecognizableInstr.cpp;h=ccd3efd980a260ae69ca45be9f286e076308c583;hb=c266600bec4b5ba0ee93ffdfeaafcab8f1295145;hp=1e14cd19b91ec3cc206330e520a07a9476192bd1;hpb=0d8db8e0a8492ab2d4bef725ec61b519471b97ec;p=oota-llvm.git diff --git a/utils/TableGen/X86RecognizableInstr.cpp b/utils/TableGen/X86RecognizableInstr.cpp index 1e14cd19b91..ccd3efd980a 100644 --- a/utils/TableGen/X86RecognizableInstr.cpp +++ b/utils/TableGen/X86RecognizableInstr.cpp @@ -24,6 +24,18 @@ using namespace llvm; +#define MRM_MAPPING \ + MAP(C1, 33) \ + MAP(C2, 34) \ + MAP(C3, 35) \ + MAP(C4, 36) \ + MAP(C8, 37) \ + MAP(C9, 38) \ + MAP(E8, 39) \ + MAP(F0, 40) \ + MAP(F8, 41) \ + MAP(F9, 42) + // A clone of X86 since we can't depend on something that is generated. namespace X86Local { enum { @@ -38,7 +50,13 @@ namespace X86Local { 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 + MRMInitReg = 32, +#define MAP(from, to) MRM_##from = to, + MRM_MAPPING +#undef MAP + RawFrmImm8 = 43, + RawFrmImm16 = 44, + lastMRM }; enum { @@ -51,7 +69,24 @@ namespace X86Local { P_0F_AE = 16, P_0F_01 = 17 }; } - + +// 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) \ @@ -79,13 +114,8 @@ namespace X86Local { EXTENSION_TABLE(72) \ EXTENSION_TABLE(73) \ EXTENSION_TABLE(ae) \ - EXTENSION_TABLE(b9) \ EXTENSION_TABLE(ba) \ EXTENSION_TABLE(c7) - -#define TWO_BYTE_FULL_EXTENSION_TABLES \ - EXTENSION_TABLE(01) - using namespace X86Disassembler; @@ -182,13 +212,14 @@ RecognizableInstr::RecognizableInstr(DisassemblerTables &tables, HasOpSizePrefix = Rec->getValueAsBit("hasOpSizePrefix"); HasREX_WPrefix = Rec->getValueAsBit("hasREX_WPrefix"); + HasVEX_4VPrefix = Rec->getValueAsBit("hasVEX_4VPrefix"); HasLockPrefix = Rec->getValueAsBit("hasLockPrefix"); IsCodeGenOnly = Rec->getValueAsBit("isCodeGenOnly"); Name = Rec->getName(); AsmString = Rec->getValueAsString("AsmString"); - Operands = &insn.OperandList; + Operands = &insn.Operands.OperandList; IsSSE = HasOpSizePrefix && (Name.find("16") == Name.npos); HasFROperands = false; @@ -200,6 +231,10 @@ void RecognizableInstr::processInstr(DisassemblerTables &tables, const CodeGenInstruction &insn, InstrUID uid) { + // Ignore "asm parser only" instructions. + if (insn.TheDef->getValueAsBit("isAsmParserOnly")) + return; + RecognizableInstr recogInstr(tables, insn, uid); recogInstr.emitInstructionSpecifier(tables); @@ -252,6 +287,10 @@ RecognizableInstr::filter_ret RecognizableInstr::filter() const { IsCodeGenOnly) return FILTER_STRONG; + if (Form == X86Local::MRMInitReg) + return FILTER_STRONG; + + // Filter out instructions with a LOCK prefix; // prefer forms that do not have the prefix if (HasLockPrefix) @@ -264,6 +303,7 @@ RecognizableInstr::filter_ret RecognizableInstr::filter() const { Name.find("_int") != Name.npos || Name.find("Int_") != Name.npos || Name.find("_NOREX") != Name.npos || + Name.find("_TC") != Name.npos || Name.find("EH_RETURN") != Name.npos || Name.find("V_SET") != Name.npos || Name.find("LOCK_") != Name.npos || @@ -271,7 +311,7 @@ RecognizableInstr::filter_ret RecognizableInstr::filter() const { return FILTER_STRONG; // Special cases. - + if (Name.find("PCMPISTRI") != Name.npos && Name != "PCMPISTRI") return FILTER_WEAK; if (Name.find("PCMPESTRI") != Name.npos && Name != "PCMPESTRI") @@ -323,9 +363,6 @@ RecognizableInstr::filter_ret RecognizableInstr::filter() const { if (AsmString.find("subreg") != AsmString.npos) return FILTER_STRONG; - assert(Form != X86Local::MRMInitReg && - "FORMAT_MRMINITREG instruction not skipped"); - if (HasFROperands && Name.find("MOV") != Name.npos && ((Name.find("2") != Name.npos && Name.find("32") == Name.npos) || (Name.find("to") != Name.npos))) @@ -387,7 +424,7 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) { Spec->insnContext = insnContext(); - const std::vector &OperandList = *Operands; + const std::vector &OperandList = *Operands; unsigned operandIndex; unsigned numOperands = OperandList.size(); @@ -403,7 +440,7 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) { for (operandIndex = 0; operandIndex < numOperands; ++operandIndex) { if (OperandList[operandIndex].Constraints.size()) { - const CodeGenInstruction::ConstraintInfo &Constraint = + const CGIOperandList::ConstraintInfo &Constraint = OperandList[operandIndex].Constraints[0]; if (Constraint.isTied()) { operandMapping[operandIndex] = Constraint.getTiedOperand(); @@ -496,7 +533,13 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) { "Unexpected number of operands for MRMSrcRegFrm"); HANDLE_OPERAND(roRegister) HANDLE_OPERAND(rmRegister) - HANDLE_OPTIONAL(immediate) + + if (HasVEX_4VPrefix) + // FIXME: In AVX, the register below becomes the one encoded + // in ModRMVEX and the one above the one in the VEX.VVVV field + HANDLE_OPTIONAL(rmRegister) + else + HANDLE_OPTIONAL(immediate) break; case X86Local::MRMSrcMem: // Operand 1 is a register operand in the Reg/Opcode field. @@ -505,6 +548,12 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) { assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 3 && "Unexpected number of operands for MRMSrcMemFrm"); HANDLE_OPERAND(roRegister) + + if (HasVEX_4VPrefix) + // FIXME: In AVX, the register below becomes the one encoded + // in ModRMVEX and the one above the one in the VEX.VVVV field + HANDLE_OPTIONAL(rmRegister) + HANDLE_OPERAND(memory) HANDLE_OPTIONAL(immediate) break; @@ -538,6 +587,20 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) { HANDLE_OPERAND(memory) HANDLE_OPTIONAL(relocation) break; + case X86Local::RawFrmImm8: + // operand 1 is a 16-bit immediate + // operand 2 is an 8-bit immediate + assert(numPhysicalOperands == 2 && + "Unexpected number of operands for X86Local::RawFrmImm8"); + HANDLE_OPERAND(immediate) + HANDLE_OPERAND(immediate) + break; + case X86Local::RawFrmImm16: + // operand 1 is a 16-bit immediate + // operand 2 is a 16-bit immediate + HANDLE_OPERAND(immediate) + HANDLE_OPERAND(immediate) + break; case X86Local::MRMInitReg: // Ignored. break; @@ -550,36 +613,10 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) { void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const { // Special cases where the LLVM tables are not complete -#define EXACTCASE(class, name, lastbyte) \ - if (Name == name) { \ - tables.setTableFields(class, \ - insnContext(), \ - Opcode, \ - ExactFilter(lastbyte), \ - UID); \ - Spec->modifierBase = Opcode; \ - return; \ - } - - EXACTCASE(TWOBYTE, "MONITOR", 0xc8) - EXACTCASE(TWOBYTE, "MWAIT", 0xc9) - EXACTCASE(TWOBYTE, "SWPGS", 0xf8) - EXACTCASE(TWOBYTE, "INVEPT", 0x80) - EXACTCASE(TWOBYTE, "INVVPID", 0x81) - EXACTCASE(TWOBYTE, "VMCALL", 0xc1) - EXACTCASE(TWOBYTE, "VMLAUNCH", 0xc2) - EXACTCASE(TWOBYTE, "VMRESUME", 0xc3) - EXACTCASE(TWOBYTE, "VMXOFF", 0xc4) - - if (Name == "INVLPG") { - tables.setTableFields(TWOBYTE, - insnContext(), - Opcode, - ExtendedFilter(false, 7), - UID); - Spec->modifierBase = Opcode; - return; - } +#define MAP(from, to) \ + case X86Local::MRM_##from: \ + filter = new ExactFilter(0x##from); \ + break; OpcodeType opcodeType = (OpcodeType)-1; @@ -594,6 +631,12 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const { 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 @@ -620,16 +663,10 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const { case X86Local::MRM7m: filter = new ExtendedFilter(false, Form - X86Local::MRM0m); break; + MRM_MAPPING } // switch (Form) break; - default: - if (needsModRMForDecode(Form)) - filter = new ModFilter(isRegFormat(Form)); - else - filter = new DumbFilter(); - - break; - } // switch (opcode) + } // switch (Opcode) opcodeToSet = Opcode; break; case X86Local::T8: @@ -697,6 +734,7 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const { case X86Local::MRM7m: filter = new ExtendedFilter(false, Form - X86Local::MRM0m); break; + MRM_MAPPING } // switch (Form) break; case 0xd8: @@ -761,6 +799,8 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const { } delete filter; + +#undef MAP } #define TYPE(str, type) if (s == str) return type; @@ -803,16 +843,21 @@ OperandType RecognizableInstr::typeFromString(const std::string &s, TYPE("GR8", TYPE_R8) TYPE("VR128", TYPE_XMM128) TYPE("f128mem", TYPE_M128) + TYPE("f256mem", TYPE_M256) TYPE("FR64", TYPE_XMM64) TYPE("f64mem", TYPE_M64FP) + TYPE("sdmem", TYPE_M64FP) TYPE("FR32", TYPE_XMM32) TYPE("f32mem", TYPE_M32FP) + TYPE("ssmem", TYPE_M32FP) TYPE("RST", TYPE_ST) TYPE("i128mem", TYPE_M128) TYPE("i64i32imm_pcrel", TYPE_REL64) + TYPE("i16imm_pcrel", TYPE_REL16) TYPE("i32imm_pcrel", TYPE_REL32) - TYPE("SSECC", TYPE_IMM8) + TYPE("SSECC", TYPE_IMM3) TYPE("brtarget", TYPE_RELv) + TYPE("uncondbrtarget", TYPE_RELv) TYPE("brtarget8", TYPE_REL8) TYPE("f80mem", TYPE_M80FP) TYPE("lea32mem", TYPE_LEA) @@ -826,8 +871,7 @@ OperandType RecognizableInstr::typeFromString(const std::string &s, TYPE("opaque512mem", TYPE_M512) TYPE("SEGMENT_REG", TYPE_SEGMENTREG) TYPE("DEBUG_REG", TYPE_DEBUGREG) - TYPE("CONTROL_REG_32", TYPE_CR32) - TYPE("CONTROL_REG_64", TYPE_CR64) + TYPE("CONTROL_REG", TYPE_CONTROLREG) TYPE("offset8", TYPE_MOFFS8) TYPE("offset16", TYPE_MOFFS16) TYPE("offset32", TYPE_MOFFS32) @@ -886,8 +930,7 @@ OperandEncoding RecognizableInstr::roRegisterEncodingFromString ENCODING("VR64", ENCODING_REG) ENCODING("SEGMENT_REG", ENCODING_REG) ENCODING("DEBUG_REG", ENCODING_REG) - ENCODING("CONTROL_REG_32", ENCODING_REG) - ENCODING("CONTROL_REG_64", ENCODING_REG) + ENCODING("CONTROL_REG", ENCODING_REG) errs() << "Unhandled reg/opcode register encoding " << s << "\n"; llvm_unreachable("Unhandled reg/opcode register encoding"); } @@ -899,7 +942,10 @@ OperandEncoding RecognizableInstr::memoryEncodingFromString ENCODING("i32mem", ENCODING_RM) ENCODING("i64mem", ENCODING_RM) ENCODING("i8mem", ENCODING_RM) + ENCODING("ssmem", ENCODING_RM) + ENCODING("sdmem", ENCODING_RM) ENCODING("f128mem", ENCODING_RM) + ENCODING("f256mem", ENCODING_RM) ENCODING("f64mem", ENCODING_RM) ENCODING("f32mem", ENCODING_RM) ENCODING("i128mem", ENCODING_RM) @@ -931,6 +977,7 @@ OperandEncoding RecognizableInstr::relocationEncodingFromString ENCODING("i64i8imm", ENCODING_IB) ENCODING("i8imm", ENCODING_IB) ENCODING("i64i32imm_pcrel", ENCODING_ID) + ENCODING("i16imm_pcrel", ENCODING_IW) ENCODING("i32imm_pcrel", ENCODING_ID) ENCODING("brtarget", ENCODING_Iv) ENCODING("brtarget8", ENCODING_IB)