X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=utils%2FTableGen%2FX86RecognizableInstr.cpp;h=805cae7b3e666e3854edd9ce6948d1c5d437dcd0;hb=db37e4072361bc44f2c0661cb1add90e74012b13;hp=5c2bf772b707b0dafb46da5965a3b6b7a4aa7371;hpb=a599de241041eebc84867ac8e4cb76668cabd236;p=oota-llvm.git diff --git a/utils/TableGen/X86RecognizableInstr.cpp b/utils/TableGen/X86RecognizableInstr.cpp index 5c2bf772b70..805cae7b3e6 100644 --- a/utils/TableGen/X86RecognizableInstr.cpp +++ b/utils/TableGen/X86RecognizableInstr.cpp @@ -33,7 +33,10 @@ using namespace llvm; MAP(C9, 38) \ MAP(E8, 39) \ MAP(F0, 40) \ - MAP(F8, 41) + MAP(F8, 41) \ + MAP(F9, 42) \ + MAP(D0, 45) \ + MAP(D1, 46) // A clone of X86 since we can't depend on something that is generated. namespace X86Local { @@ -50,10 +53,11 @@ namespace X86Local { MRM0m = 24, MRM1m = 25, MRM2m = 26, MRM3m = 27, MRM4m = 28, MRM5m = 29, MRM6m = 30, MRM7m = 31, MRMInitReg = 32, - #define MAP(from, to) MRM_##from = to, MRM_MAPPING #undef MAP + RawFrmImm8 = 43, + RawFrmImm16 = 44, lastMRM }; @@ -112,7 +116,6 @@ namespace X86Local { EXTENSION_TABLE(72) \ EXTENSION_TABLE(73) \ EXTENSION_TABLE(ae) \ - EXTENSION_TABLE(b9) \ EXTENSION_TABLE(ba) \ EXTENSION_TABLE(c7) @@ -211,16 +214,20 @@ RecognizableInstr::RecognizableInstr(DisassemblerTables &tables, HasOpSizePrefix = Rec->getValueAsBit("hasOpSizePrefix"); HasREX_WPrefix = Rec->getValueAsBit("hasREX_WPrefix"); + HasVEXPrefix = Rec->getValueAsBit("hasVEXPrefix"); + HasVEX_4VPrefix = Rec->getValueAsBit("hasVEX_4VPrefix"); + HasVEX_WPrefix = Rec->getValueAsBit("hasVEX_WPrefix"); 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; + HasFROperands = hasFROperands(); + HasVEX_LPrefix = has256BitOperands() || Rec->getValueAsBit("hasVEX_L"); ShouldBeEmitted = true; } @@ -229,6 +236,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); @@ -240,7 +251,32 @@ void RecognizableInstr::processInstr(DisassemblerTables &tables, InstructionContext RecognizableInstr::insnContext() const { InstructionContext insnContext; - if (Name.find("64") != Name.npos || HasREX_WPrefix) { + if (HasVEX_4VPrefix || HasVEXPrefix) { + if (HasOpSizePrefix && HasVEX_LPrefix) + insnContext = IC_VEX_L_OPSIZE; + else if (HasOpSizePrefix && HasVEX_WPrefix) + insnContext = IC_VEX_W_OPSIZE; + else if (HasOpSizePrefix) + insnContext = IC_VEX_OPSIZE; + else if (HasVEX_LPrefix && Prefix == X86Local::XS) + insnContext = IC_VEX_L_XS; + else if (HasVEX_LPrefix && Prefix == X86Local::XD) + insnContext = IC_VEX_L_XD; + else if (HasVEX_WPrefix && Prefix == X86Local::XS) + insnContext = IC_VEX_W_XS; + else if (HasVEX_WPrefix && Prefix == X86Local::XD) + insnContext = IC_VEX_W_XD; + else if (HasVEX_WPrefix) + insnContext = IC_VEX_W; + else if (HasVEX_LPrefix) + insnContext = IC_VEX_L; + else if (Prefix == X86Local::XD) + insnContext = IC_VEX_XD; + else if (Prefix == X86Local::XS) + insnContext = IC_VEX_XS; + else + insnContext = IC_VEX; + } else if (Name.find("64") != Name.npos || HasREX_WPrefix) { if (HasREX_WPrefix && HasOpSizePrefix) insnContext = IC_64BIT_REXW_OPSIZE; else if (HasOpSizePrefix) @@ -272,6 +308,10 @@ InstructionContext RecognizableInstr::insnContext() const { } RecognizableInstr::filter_ret RecognizableInstr::filter() const { + /////////////////// + // FILTER_STRONG + // + // Filter out intrinsics if (!Rec->isSubClassOf("X86Inst")) @@ -281,26 +321,76 @@ RecognizableInstr::filter_ret RecognizableInstr::filter() const { IsCodeGenOnly) return FILTER_STRONG; + if (Form == X86Local::MRMInitReg) + return FILTER_STRONG; + + + // TEMPORARY pending bug fixes + + if (Name.find("VMOVDQU") != Name.npos || + Name.find("VMOVDQA") != Name.npos || + Name.find("VROUND") != Name.npos) + return FILTER_STRONG; + + // Filter out artificial instructions + + if (Name.find("TAILJMP") != Name.npos || + Name.find("_Int") != Name.npos || + 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 || + Name.find("WIN") != Name.npos || + Name.find("_AVX") != Name.npos || + Name.find("2SDL") != Name.npos) + return FILTER_STRONG; + + // Filter out instructions with segment override prefixes. + // They're too messy to handle now and we'll special case them if needed. + + if (SegOvr) + return FILTER_STRONG; + + // Filter out instructions that can't be printed. + + if (AsmString.size() == 0) + return FILTER_STRONG; + + // Filter out instructions with subreg operands. + + if (AsmString.find("subreg") != AsmString.npos) + return FILTER_STRONG; + + ///////////////// + // FILTER_WEAK + // + + // Filter out instructions with a LOCK prefix; // prefer forms that do not have the prefix if (HasLockPrefix) return FILTER_WEAK; - - // Filter out artificial instructions - if (Name.find("TAILJMP") != Name.npos || - Name.find("_Int") != Name.npos || - Name.find("_int") != Name.npos || - Name.find("Int_") != Name.npos || - Name.find("_NOREX") != Name.npos || - Name.find("EH_RETURN") != Name.npos || - Name.find("V_SET") != Name.npos || - Name.find("LOCK_") != Name.npos || - Name.find("WIN") != Name.npos) - return FILTER_STRONG; + // Filter out alternate forms of AVX instructions + if (Name.find("_alt") != Name.npos || + Name.find("XrYr") != Name.npos || + Name.find("r64r") != Name.npos || + Name.find("_64mr") != Name.npos || + Name.find("Xrr") != Name.npos || + Name.find("rr64") != Name.npos) + return FILTER_WEAK; + + if (Name == "VMASKMOVDQU64" || + Name == "VEXTRACTPSrr64" || + Name == "VMOVQd64rr" || + Name == "VMOVQs64rr") + return FILTER_WEAK; // Special cases. - + if (Name.find("PCMPISTRI") != Name.npos && Name != "PCMPISTRI") return FILTER_WEAK; if (Name.find("PCMPESTRI") != Name.npos && Name != "PCMPESTRI") @@ -326,6 +416,7 @@ RecognizableInstr::filter_ret RecognizableInstr::filter() const { Name == "PUSH32i16" || Name == "PUSH64i16" || Name == "MOVPQI2QImr" || + Name == "VMOVPQI2QImr" || Name == "MOVSDmr" || Name == "MOVSDrm" || Name == "MOVSSmr" || @@ -336,25 +427,6 @@ RecognizableInstr::filter_ret RecognizableInstr::filter() const { Name == "CRC32r16") return FILTER_WEAK; - // Filter out instructions with segment override prefixes. - // They're too messy to handle now and we'll special case them if needed. - - if (SegOvr) - return FILTER_STRONG; - - // Filter out instructions that can't be printed. - - if (AsmString.size() == 0) - return FILTER_STRONG; - - // Filter out instructions with subreg operands. - - 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))) @@ -362,6 +434,33 @@ RecognizableInstr::filter_ret RecognizableInstr::filter() const { return FILTER_NORMAL; } + +bool RecognizableInstr::hasFROperands() const { + const std::vector &OperandList = *Operands; + unsigned numOperands = OperandList.size(); + + for (unsigned operandIndex = 0; operandIndex < numOperands; ++operandIndex) { + const std::string &recName = OperandList[operandIndex].Rec->getName(); + + if (recName.find("FR") != recName.npos) + return true; + } + return false; +} + +bool RecognizableInstr::has256BitOperands() const { + const std::vector &OperandList = *Operands; + unsigned numOperands = OperandList.size(); + + for (unsigned operandIndex = 0; operandIndex < numOperands; ++operandIndex) { + const std::string &recName = OperandList[operandIndex].Rec->getName(); + + if (!recName.compare("VR256") || !recName.compare("f256mem")) { + return true; + } + } + return false; +} void RecognizableInstr::handleOperand( bool optional, @@ -385,13 +484,13 @@ void RecognizableInstr::handleOperand( } const std::string &typeName = (*Operands)[operandIndex].Rec->getName(); - + Spec->operands[operandIndex].encoding = encodingFromString(typeName, HasOpSizePrefix); Spec->operands[operandIndex].type = typeFromString(typeName, - IsSSE, - HasREX_WPrefix, - HasOpSizePrefix); + IsSSE, + HasREX_WPrefix, + HasOpSizePrefix); ++operandIndex; ++physicalOperandIndex; @@ -416,7 +515,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(); @@ -432,7 +531,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(); @@ -520,20 +619,46 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) { case X86Local::MRMSrcReg: // Operand 1 is a register operand in the Reg/Opcode field. // Operand 2 is a register operand in the R/M field. + // - In AVX, there is a register operand in the VEX.vvvv field here - // Operand 3 (optional) is an immediate. - assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 3 && - "Unexpected number of operands for MRMSrcRegFrm"); + + if (HasVEX_4VPrefix) + assert(numPhysicalOperands >= 3 && numPhysicalOperands <= 4 && + "Unexpected number of operands for MRMSrcRegFrm with VEX_4V"); + else + assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 3 && + "Unexpected number of operands for MRMSrcRegFrm"); + 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_OPERAND(vvvvRegister) + HANDLE_OPERAND(rmRegister) HANDLE_OPTIONAL(immediate) break; case X86Local::MRMSrcMem: // Operand 1 is a register operand in the Reg/Opcode field. // Operand 2 is a memory operand (possibly SIB-extended) + // - In AVX, there is a register operand in the VEX.vvvv field here - // Operand 3 (optional) is an immediate. - assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 3 && - "Unexpected number of operands for MRMSrcMemFrm"); + + if (HasVEX_4VPrefix) + assert(numPhysicalOperands >= 3 && numPhysicalOperands <= 4 && + "Unexpected number of operands for MRMSrcMemFrm with VEX_4V"); + else + 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_OPERAND(vvvvRegister) + HANDLE_OPERAND(memory) HANDLE_OPTIONAL(immediate) break; @@ -547,8 +672,14 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) { case X86Local::MRM7r: // Operand 1 is a register operand in the R/M field. // Operand 2 (optional) is an immediate or relocation. - assert(numPhysicalOperands <= 2 && - "Unexpected number of operands for MRMnRFrm"); + if (HasVEX_4VPrefix) + assert(numPhysicalOperands <= 3 && + "Unexpected number of operands for MRMSrcMemFrm with VEX_4V"); + else + assert(numPhysicalOperands <= 2 && + "Unexpected number of operands for MRMnRFrm"); + if (HasVEX_4VPrefix) + HANDLE_OPERAND(vvvvRegister); HANDLE_OPTIONAL(rmRegister) HANDLE_OPTIONAL(relocation) break; @@ -567,6 +698,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; @@ -583,30 +728,6 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const { case X86Local::MRM_##from: \ filter = new ExactFilter(0x##from); \ break; - -#define EXACTCASE(class, name, lastbyte) \ - if (Name == name) { \ - tables.setTableFields(class, \ - insnContext(), \ - Opcode, \ - ExactFilter(lastbyte), \ - UID); \ - Spec->modifierBase = Opcode; \ - return; \ - } - - EXACTCASE(TWOBYTE, "INVEPT", 0x80) - EXACTCASE(TWOBYTE, "INVVPID", 0x81) - - if (Name == "INVLPG") { - tables.setTableFields(TWOBYTE, - insnContext(), - Opcode, - ExtendedFilter(false, 7), - UID); - Spec->modifierBase = Opcode; - return; - } OpcodeType opcodeType = (OpcodeType)-1; @@ -621,6 +742,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 @@ -650,14 +777,7 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const { 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: @@ -834,16 +954,22 @@ 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("i256mem", TYPE_M256) 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) @@ -857,12 +983,12 @@ 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) TYPE("offset64", TYPE_MOFFS64) + TYPE("VR256", TYPE_XMM256) errs() << "Unhandled type string " << s << "\n"; llvm_unreachable("Unhandled type string"); } @@ -885,6 +1011,10 @@ OperandEncoding RecognizableInstr::immediateEncodingFromString ENCODING("i64i32imm", ENCODING_ID) ENCODING("i64i8imm", ENCODING_IB) ENCODING("i8imm", ENCODING_IB) + // This is not a typo. Instructions like BLENDVPD put + // register IDs in 8-bit immediates nowadays. + ENCODING("VR256", ENCODING_IB) + ENCODING("VR128", ENCODING_IB) errs() << "Unhandled immediate encoding " << s << "\n"; llvm_unreachable("Unhandled immediate encoding"); } @@ -900,6 +1030,7 @@ OperandEncoding RecognizableInstr::rmRegisterEncodingFromString ENCODING("FR64", ENCODING_RM) ENCODING("FR32", ENCODING_RM) ENCODING("VR64", ENCODING_RM) + ENCODING("VR256", ENCODING_RM) errs() << "Unhandled R/M register encoding " << s << "\n"; llvm_unreachable("Unhandled R/M register encoding"); } @@ -917,12 +1048,23 @@ 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) + ENCODING("VR256", ENCODING_REG) errs() << "Unhandled reg/opcode register encoding " << s << "\n"; llvm_unreachable("Unhandled reg/opcode register encoding"); } +OperandEncoding RecognizableInstr::vvvvRegisterEncodingFromString + (const std::string &s, + bool hasOpSizePrefix) { + ENCODING("FR32", ENCODING_VVVV) + ENCODING("FR64", ENCODING_VVVV) + ENCODING("VR128", ENCODING_VVVV) + ENCODING("VR256", ENCODING_VVVV) + errs() << "Unhandled VEX.vvvv register encoding " << s << "\n"; + llvm_unreachable("Unhandled VEX.vvvv register encoding"); +} + OperandEncoding RecognizableInstr::memoryEncodingFromString (const std::string &s, bool hasOpSizePrefix) { @@ -930,10 +1072,14 @@ 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) + ENCODING("i256mem", ENCODING_RM) ENCODING("f80mem", ENCODING_RM) ENCODING("lea32mem", ENCODING_RM) ENCODING("lea64_32mem", ENCODING_RM) @@ -962,6 +1108,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)