X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=utils%2FTableGen%2FARMDecoderEmitter.cpp;h=21af62050d72eab6946cded653f11778087e70e5;hb=75f6e89ea9f8fe9cf8c8f9fe6a3322bd6566fdf1;hp=230152195ed505f5293ed3787e775f9bdb68fe4f;hpb=3c500e6947ed8db719d87d47572de86e107ec094;p=oota-llvm.git diff --git a/utils/TableGen/ARMDecoderEmitter.cpp b/utils/TableGen/ARMDecoderEmitter.cpp index 230152195ed..21af62050d7 100644 --- a/utils/TableGen/ARMDecoderEmitter.cpp +++ b/utils/TableGen/ARMDecoderEmitter.cpp @@ -49,36 +49,35 @@ using namespace llvm; ENTRY(ARM_FORMAT_LDSTMULFRM, 10) \ ENTRY(ARM_FORMAT_LDSTEXFRM, 11) \ ENTRY(ARM_FORMAT_ARITHMISCFRM, 12) \ - ENTRY(ARM_FORMAT_EXTFRM, 13) \ - ENTRY(ARM_FORMAT_VFPUNARYFRM, 14) \ - ENTRY(ARM_FORMAT_VFPBINARYFRM, 15) \ - ENTRY(ARM_FORMAT_VFPCONV1FRM, 16) \ - ENTRY(ARM_FORMAT_VFPCONV2FRM, 17) \ - ENTRY(ARM_FORMAT_VFPCONV3FRM, 18) \ - ENTRY(ARM_FORMAT_VFPCONV4FRM, 19) \ - ENTRY(ARM_FORMAT_VFPCONV5FRM, 20) \ - ENTRY(ARM_FORMAT_VFPLDSTFRM, 21) \ - ENTRY(ARM_FORMAT_VFPLDSTMULFRM, 22) \ - ENTRY(ARM_FORMAT_VFPMISCFRM, 23) \ - ENTRY(ARM_FORMAT_THUMBFRM, 24) \ - ENTRY(ARM_FORMAT_NEONFRM, 25) \ - ENTRY(ARM_FORMAT_NEONGETLNFRM, 26) \ - ENTRY(ARM_FORMAT_NEONSETLNFRM, 27) \ - ENTRY(ARM_FORMAT_NEONDUPFRM, 28) \ - ENTRY(ARM_FORMAT_MISCFRM, 29) \ - ENTRY(ARM_FORMAT_THUMBMISCFRM, 30) \ - ENTRY(ARM_FORMAT_NLdSt, 31) \ - ENTRY(ARM_FORMAT_N1RegModImm, 32) \ - ENTRY(ARM_FORMAT_N2Reg, 33) \ - ENTRY(ARM_FORMAT_NVCVT, 34) \ - ENTRY(ARM_FORMAT_NVecDupLn, 35) \ - ENTRY(ARM_FORMAT_N2RegVecShL, 36) \ - ENTRY(ARM_FORMAT_N2RegVecShR, 37) \ - ENTRY(ARM_FORMAT_N3Reg, 38) \ - ENTRY(ARM_FORMAT_N3RegVecSh, 39) \ - ENTRY(ARM_FORMAT_NVecExtract, 40) \ - ENTRY(ARM_FORMAT_NVecMulScalar, 41) \ - ENTRY(ARM_FORMAT_NVTBL, 42) + ENTRY(ARM_FORMAT_SATFRM, 13) \ + ENTRY(ARM_FORMAT_EXTFRM, 14) \ + ENTRY(ARM_FORMAT_VFPUNARYFRM, 15) \ + ENTRY(ARM_FORMAT_VFPBINARYFRM, 16) \ + ENTRY(ARM_FORMAT_VFPCONV1FRM, 17) \ + ENTRY(ARM_FORMAT_VFPCONV2FRM, 18) \ + ENTRY(ARM_FORMAT_VFPCONV3FRM, 19) \ + ENTRY(ARM_FORMAT_VFPCONV4FRM, 20) \ + ENTRY(ARM_FORMAT_VFPCONV5FRM, 21) \ + ENTRY(ARM_FORMAT_VFPLDSTFRM, 22) \ + ENTRY(ARM_FORMAT_VFPLDSTMULFRM, 23) \ + ENTRY(ARM_FORMAT_VFPMISCFRM, 24) \ + ENTRY(ARM_FORMAT_THUMBFRM, 25) \ + ENTRY(ARM_FORMAT_MISCFRM, 26) \ + ENTRY(ARM_FORMAT_NEONGETLNFRM, 27) \ + ENTRY(ARM_FORMAT_NEONSETLNFRM, 28) \ + ENTRY(ARM_FORMAT_NEONDUPFRM, 29) \ + ENTRY(ARM_FORMAT_NLdSt, 30) \ + ENTRY(ARM_FORMAT_N1RegModImm, 31) \ + ENTRY(ARM_FORMAT_N2Reg, 32) \ + ENTRY(ARM_FORMAT_NVCVT, 33) \ + ENTRY(ARM_FORMAT_NVecDupLn, 34) \ + ENTRY(ARM_FORMAT_N2RegVecShL, 35) \ + ENTRY(ARM_FORMAT_N2RegVecShR, 36) \ + ENTRY(ARM_FORMAT_N3Reg, 37) \ + ENTRY(ARM_FORMAT_N3RegVecSh, 38) \ + ENTRY(ARM_FORMAT_NVecExtract, 39) \ + ENTRY(ARM_FORMAT_NVecMulScalar, 40) \ + ENTRY(ARM_FORMAT_NVTBL, 41) // ARM instruction format specifies the encoding used by the instruction. #define ENTRY(n, v) n = v, @@ -241,7 +240,7 @@ typedef bit_value_t insn_t[BIT_WIDTH]; /// the Filter/FilterChooser combo does not know how to distinguish among the /// Opcodes assigned. /// -/// An example of a conflcit is +/// An example of a conflict is /// /// Conflict: /// 111101000.00........00010000.... @@ -596,11 +595,7 @@ void Filter::recurse() { bit_value_t BitValueArray[BIT_WIDTH]; // Starts by inheriting our parent filter chooser's filter bit values. - bit_value_t *BitVals = Owner->FilterBitValues; - for (unsigned i = 0; i < BIT_WIDTH; ++i) - BitValueArray[i] = BitVals[i]; - // FIXME: memcpy() is optmized out with self-hosting llvm-gcc (-O1 and -O2). - //memcpy(BitValueArray, Owner->FilterBitValues, sizeof(BitValueArray)); + memcpy(BitValueArray, Owner->FilterBitValues, sizeof(BitValueArray)); unsigned bitIndex; @@ -635,7 +630,7 @@ void Filter::recurse() { // Marks all the segment positions with either BIT_TRUE or BIT_FALSE. for (bitIndex = 0; bitIndex < NumBits; bitIndex++) { - if (mapIterator->first & (1 << bitIndex)) + if (mapIterator->first & (1ULL << bitIndex)) BitValueArray[StartBit + bitIndex] = BIT_TRUE; else BitValueArray[StartBit + bitIndex] = BIT_FALSE; @@ -806,7 +801,7 @@ void FilterChooser::emitTop(raw_ostream &o, unsigned &Indentation) { o << '\n'; - o.indent(Indentation) << "static uint16_t decodeInstruction(field_t insn) {\n"; + o.indent(Indentation) <<"static uint16_t decodeInstruction(field_t insn) {\n"; ++Indentation; ++Indentation; // Emits code to decode the instructions. @@ -857,7 +852,7 @@ bool FilterChooser::fieldFromInsn(uint64_t &Field, insn_t &Insn, return false; if (Insn[StartBit + i] == BIT_TRUE) - Field = Field | (1 << i); + Field = Field | (1ULL << i); } return true; @@ -1348,23 +1343,8 @@ void FilterChooser::doFilter() { return; // If we come to here, the instruction decoding has failed. - // Print out the instructions in the conflict set... + // Set the BestIndex to -1 to indicate so. BestIndex = -1; - - DEBUG({ - errs() << "Conflict:\n"; - - dumpStack(errs(), "\t\t"); - - for (unsigned i = 0; i < Num; i++) { - const std::string &Name = nameWithID(Opcodes[i]); - - errs() << '\t' << Name << " "; - dumpBits(errs(), - getBitsField(*AllInstructions[Opcodes[i]]->TheDef, "Inst")); - errs() << '\n'; - } - }); } // Emits code to decode our share of instructions. Returns true if the @@ -1469,7 +1449,9 @@ bool FilterChooser::emit(raw_ostream &o, unsigned &Indentation) { // Otherwise, it does not belong to the known conflict sets. } - // We don't know how to decode these instructions! Dump the conflict set! + + // We don't know how to decode these instructions! Return 0 and dump the + // conflict set! o.indent(Indentation) << "return 0;" << " // Conflict set: "; for (int i = 0, N = Opcodes.size(); i < N; ++i) { o << nameWithID(Opcodes[i]); @@ -1478,6 +1460,21 @@ bool FilterChooser::emit(raw_ostream &o, unsigned &Indentation) { else o << '\n'; } + + // Print out useful conflict information for postmortem analysis. + errs() << "Decoding Conflict:\n"; + + dumpStack(errs(), "\t\t"); + + for (unsigned i = 0; i < Opcodes.size(); i++) { + const std::string &Name = nameWithID(Opcodes[i]); + + errs() << '\t' << Name << " "; + dumpBits(errs(), + getBitsField(*AllInstructions[Opcodes[i]]->TheDef, "Inst")); + errs() << '\n'; + } + return true; } @@ -1491,11 +1488,11 @@ bool FilterChooser::emit(raw_ostream &o, unsigned &Indentation) { class ARMDecoderEmitter::ARMDEBackend { public: - ARMDEBackend(ARMDecoderEmitter &frontend) : + ARMDEBackend(ARMDecoderEmitter &frontend, RecordKeeper &Records) : NumberedInstructions(), Opcodes(), Frontend(frontend), - Target(), + Target(Records), FC(NULL) { if (Target.getName() == "ARM") @@ -1546,12 +1543,27 @@ protected: TARGET_NAME_t TargetName; }; -bool ARMDecoderEmitter::ARMDEBackend::populateInstruction( - const CodeGenInstruction &CGI, TARGET_NAME_t TN) { +bool ARMDecoderEmitter:: +ARMDEBackend::populateInstruction(const CodeGenInstruction &CGI, + TARGET_NAME_t TN) { const Record &Def = *CGI.TheDef; const StringRef Name = Def.getName(); uint8_t Form = getByteField(Def, "Form"); + BitsInit &Bits = getBitsField(Def, "Inst"); + + // If all the bit positions are not specified; do not decode this instruction. + // We are bound to fail! For proper disassembly, the well-known encoding bits + // of the instruction must be fully specified. + // + // This also removes pseudo instructions from considerations of disassembly, + // which is a better design and less fragile than the name matchings. + if (Bits.allInComplete()) return false; + + // Ignore "asm parser only" instructions. + if (Def.getValueAsBit("isAsmParserOnly")) + return false; + if (TN == TARGET_ARM) { // FIXME: what about Int_MemBarrierV6 and Int_SyncBarrierV6? if ((Name != "Int_MemBarrierV7" && Name != "Int_SyncBarrierV7") && @@ -1559,17 +1571,14 @@ bool ARMDecoderEmitter::ARMDEBackend::populateInstruction( return false; if (thumbInstruction(Form)) return false; - if (Name.find("CMPz") != std::string::npos /* || - Name.find("CMNz") != std::string::npos */) - return false; - // Ignore pseudo instructions. - if (Name == "BXr9" || Name == "BMOVPCRX" || Name == "BMOVPCRXr9") - return false; - - // VLDMQ/VSTMQ can be hanlded with the more generic VLDMD/VSTMD. - if (Name == "VLDMQ" || Name == "VLDMQ_UPD" || - Name == "VSTMQ" || Name == "VSTMQ_UPD") + // Tail calls are other patterns that generate existing instructions. + if (Name == "TCRETURNdi" || Name == "TCRETURNdiND" || + Name == "TCRETURNri" || Name == "TCRETURNriND" || + Name == "TAILJMPd" || Name == "TAILJMPdt" || + Name == "TAILJMPdND" || Name == "TAILJMPdNDt" || + Name == "TAILJMPr" || Name == "TAILJMPrND" || + Name == "MOVr_TC") return false; // @@ -1594,13 +1603,13 @@ bool ARMDecoderEmitter::ARMDEBackend::populateInstruction( // better off using the generic RSCri and RSCrs instructions. if (Name == "RSCSri" || Name == "RSCSrs") return false; - // MOVCCr, MOVCCs, MOVCCi, FCYPScc, FCYPDcc, FNEGScc, and FNEGDcc are used - // in the compiler to implement conditional moves. We can ignore them in - // favor of their more generic versions of instructions. - // See also SDNode *ARMDAGToDAGISel::Select(SDValue Op). - if (Name == "MOVCCr" || Name == "MOVCCs" || Name == "MOVCCi" || - Name == "FCPYScc" || Name == "FCPYDcc" || - Name == "FNEGScc" || Name == "FNEGDcc") + // MOVCCr, MOVCCs, MOVCCi, MOVCCi16, FCYPScc, FCYPDcc, FNEGScc, and + // FNEGDcc are used in the compiler to implement conditional moves. + // We can ignore them in favor of their more generic versions of + // instructions. See also SDNode *ARMDAGToDAGISel::Select(SDValue Op). + if (Name == "MOVCCr" || Name == "MOVCCs" || Name == "MOVCCi" || + Name == "MOVCCi16" || Name == "FCPYScc" || Name == "FCPYDcc" || + Name == "FNEGScc" || Name == "FNEGDcc") return false; // Ditto for VMOVDcc, VMOVScc, VNEGDcc, and VNEGScc. @@ -1608,15 +1617,10 @@ bool ARMDecoderEmitter::ARMDEBackend::populateInstruction( Name == "VNEGScc") return false; - // Ignore the *_sfp instructions when decoding. They are used by the - // compiler to implement scalar floating point operations using vector - // operations in order to work around some performance issues. - if (Name.find("_sfp") != std::string::npos) return false; - - // LDM_RET is a special case of LDM (Load Multiple) where the registers + // LDMIA_RET is a special case of LDM (Load Multiple) where the registers // loaded include the PC, causing a branch to a loaded address. Ignore - // the LDM_RET instruction when decoding. - if (Name == "LDM_RET") return false; + // the LDMIA_RET instruction when decoding. + if (Name == "LDMIA_RET") return false; // Bcc is in a more generic form than B. Ignore B when decoding. if (Name == "B") return false; @@ -1655,28 +1659,22 @@ bool ARMDecoderEmitter::ARMDEBackend::populateInstruction( // VREV64qf is equivalent to VREV64q32. if (Name == "VREV64df" || Name == "VREV64qf") return false; - // VDUPLNfd is equivalent to VDUPLN32d; VDUPfdf is specialized VDUPLN32d. - // VDUPLNfq is equivalent to VDUPLN32q; VDUPfqf is specialized VDUPLN32q. + // VDUPLNfd is equivalent to VDUPLN32d. + // VDUPLNfq is equivalent to VDUPLN32q. // VLD1df is equivalent to VLD1d32. // VLD1qf is equivalent to VLD1q32. // VLD2d64 is equivalent to VLD1q64. // VST1df is equivalent to VST1d32. // VST1qf is equivalent to VST1q32. // VST2d64 is equivalent to VST1q64. - if (Name == "VDUPLNfd" || Name == "VDUPfdf" || - Name == "VDUPLNfq" || Name == "VDUPfqf" || - Name == "VLD1df" || Name == "VLD1qf" || Name == "VLD2d64" || - Name == "VST1df" || Name == "VST1qf" || Name == "VST2d64") + if (Name == "VDUPLNfd" || Name == "VDUPLNfq" || + Name == "VLD1df" || Name == "VLD1qf" || Name == "VLD2d64" || + Name == "VST1df" || Name == "VST1qf" || Name == "VST2d64") return false; } else if (TN == TARGET_THUMB) { if (!thumbInstruction(Form)) return false; - // Ignore pseudo instructions. - if (Name == "tInt_eh_sjlj_setjmp" || Name == "t2Int_eh_sjlj_setjmp" || - Name == "t2MOVi32imm" || Name == "tBX" || Name == "tBXr9") - return false; - // On Darwin R9 is call-clobbered. Ignore the non-Darwin counterparts. if (Name == "tBL" || Name == "tBLXi" || Name == "tBLXr") return false; @@ -1685,63 +1683,51 @@ bool ARMDecoderEmitter::ARMDEBackend::populateInstruction( if (Name == "tTPsoft" || Name == "t2TPsoft") return false; - // Ignore tLEApcrel and tLEApcrelJT, prefer tADDrPCi. - if (Name == "tLEApcrel" || Name == "tLEApcrelJT") - return false; - - // Ignore t2LEApcrel, prefer the generic t2ADD* for disassembly printing. - if (Name == "t2LEApcrel") + // Ignore tADR, prefer tADDrPCi. + if (Name == "tADR") return false; // Ignore tADDrSP, tADDspr, and tPICADD, prefer the generic tADDhirr. // Ignore t2SUBrSPs, prefer the t2SUB[S]r[r|s]. // Ignore t2ADDrSPs, prefer the t2ADD[S]r[r|s]. + // Ignore t2ADDrSPi/t2SUBrSPi, which have more generic couterparts. + // Ignore t2ADDrSPi12/t2SUBrSPi12, which have more generic couterparts if (Name == "tADDrSP" || Name == "tADDspr" || Name == "tPICADD" || - Name == "t2SUBrSPs" || Name == "t2ADDrSPs") + Name == "t2SUBrSPs" || Name == "t2ADDrSPs" || + Name == "t2ADDrSPi" || Name == "t2SUBrSPi" || + Name == "t2ADDrSPi12" || Name == "t2SUBrSPi12") return false; // Ignore t2LDRDpci, prefer the generic t2LDRDi8, t2LDRD_PRE, t2LDRD_POST. if (Name == "t2LDRDpci") return false; - // Ignore t2TBB, t2TBH and prefer the generic t2TBBgen, t2TBHgen. - if (Name == "t2TBB" || Name == "t2TBH") - return false; - // Resolve conflicts: // // tBfar conflicts with tBLr9 - // tCMNz conflicts with tCMN (with assembly format strings being equal) - // tPOP_RET/t2LDM_RET conflict with tPOP/t2LDM (ditto) + // tPOP_RET/t2LDMIA_RET conflict with tPOP/t2LDM (ditto) // tMOVCCi conflicts with tMOVi8 // tMOVCCr conflicts with tMOVgpr2gpr - // tBR_JTr conflicts with tBRIND // tSpill conflicts with tSTRspi // tLDRcp conflicts with tLDRspi // tRestore conflicts with tLDRspi - // t2LEApcrelJT conflicts with t2LEApcrel - // t2ADDrSPi/t2SUBrSPi have more generic couterparts + // t2MOVCCi16 conflicts with tMOVi16 if (Name == "tBfar" || - /* Name == "tCMNz" || */ Name == "tCMPzi8" || Name == "tCMPzr" || - Name == "tCMPzhir" || /* Name == "t2CMNzrr" || Name == "t2CMNzrs" || - Name == "t2CMNzri" || */ Name == "t2CMPzrr" || Name == "t2CMPzrs" || - Name == "t2CMPzri" || Name == "tPOP_RET" || Name == "t2LDM_RET" || - Name == "tMOVCCi" || Name == "tMOVCCr" || Name == "tBR_JTr" || + Name == "tPOP_RET" || Name == "t2LDMIA_RET" || + Name == "tMOVCCi" || Name == "tMOVCCr" || Name == "tSpill" || Name == "tLDRcp" || Name == "tRestore" || - Name == "t2LEApcrelJT" || Name == "t2ADDrSPi" || Name == "t2SUBrSPi") + Name == "t2MOVCCi16") return false; } - // Dumps the instruction encoding format. - switch (TargetName) { - case TARGET_ARM: - case TARGET_THUMB: - DEBUG(errs() << Name << " " << stringForARMFormat((ARMFormat)Form)); - break; - } - DEBUG({ - BitsInit &Bits = getBitsField(Def, "Inst"); + // Dumps the instruction encoding format. + switch (TargetName) { + case TARGET_ARM: + case TARGET_THUMB: + errs() << Name << " " << stringForARMFormat((ARMFormat)Form); + break; + } errs() << " "; @@ -1751,8 +1737,8 @@ bool ARMDecoderEmitter::ARMDEBackend::populateInstruction( errs() << '\n'; // Dumps the list of operand info. - for (unsigned i = 0, e = CGI.OperandList.size(); i != e; ++i) { - CodeGenInstruction::OperandInfo Info = CGI.OperandList[i]; + for (unsigned i = 0, e = CGI.Operands.size(); i != e; ++i) { + const CGIOperandList::OperandInfo &Info = CGI.Operands[i]; const std::string &OperandName = Info.Name; const Record &OperandDef = *Info.Rec; @@ -1814,7 +1800,7 @@ void ARMDecoderEmitter::ARMDEBackend::emit(raw_ostream &o) { assert(0 && "Unreachable code!"); } - o << "#include \"llvm/System/DataTypes.h\"\n"; + o << "#include \"llvm/Support/DataTypes.h\"\n"; o << "#include \n"; o << '\n'; o << "namespace llvm {\n\n"; @@ -1851,7 +1837,7 @@ void ARMDecoderEmitter::ARMDEBackend::emit(raw_ostream &o) { void ARMDecoderEmitter::initBackend() { - Backend = new ARMDEBackend(*this); + Backend = new ARMDEBackend(*this, Records); } void ARMDecoderEmitter::run(raw_ostream &o)