X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=blobdiff_plain;f=lib%2FTarget%2FARM%2FAsmParser%2FARMAsmParser.cpp;h=2d291bf8652cbcd5128a05d32364b5610016aef1;hp=d0cd04b66d5fccfe858aee91dc240906f9c73ca3;hb=299ab3d150fbaf92455b61e786ee5888e8b798fb;hpb=9bd0d2a6a02750f51633ea20394c37a9c5457eaa diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index d0cd04b66d5..2d291bf8652 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -7,10 +7,8 @@ // //===----------------------------------------------------------------------===// -#include "ARMFPUName.h" #include "ARMFeatures.h" #include "MCTargetDesc/ARMAddressingModes.h" -#include "MCTargetDesc/ARMArchName.h" #include "MCTargetDesc/ARMBaseInfo.h" #include "MCTargetDesc/ARMMCExpr.h" #include "llvm/ADT/STLExtras.h" @@ -30,6 +28,7 @@ #include "llvm/MC/MCObjectFileInfo.h" #include "llvm/MC/MCParser/MCAsmLexer.h" #include "llvm/MC/MCParser/MCAsmParser.h" +#include "llvm/MC/MCParser/MCAsmParserUtils.h" #include "llvm/MC/MCParser/MCParsedAsmOperand.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSection.h" @@ -39,6 +38,7 @@ #include "llvm/MC/MCTargetAsmParser.h" #include "llvm/Support/ARMBuildAttributes.h" #include "llvm/Support/ARMEHABI.h" +#include "llvm/Support/TargetParser.h" #include "llvm/Support/COFF.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ELF.h" @@ -129,12 +129,13 @@ public: class ARMAsmParser : public MCTargetAsmParser { MCSubtargetInfo &STI; - MCAsmParser &Parser; const MCInstrInfo &MII; const MCRegisterInfo *MRI; UnwindContext UC; ARMTargetStreamer &getTargetStreamer() { + assert(getParser().getStreamer().getTargetStreamer() && + "do not have a target streamer"); MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer(); return static_cast(TS); } @@ -163,7 +164,10 @@ class ARMAsmParser : public MCTargetAsmParser { // according to count of instructions in block. // ~0U if no active IT block. } ITState; - bool inITBlock() { return ITState.CurPosition != ~0U;} + bool inITBlock() { return ITState.CurPosition != ~0U; } + bool lastInITBlock() { + return ITState.CurPosition == 4 - countTrailingZeros(ITState.Mask); + } void forwardITPosition() { if (!inITBlock()) return; // Move to the next instruction in the IT block, if there is one. If not, @@ -173,22 +177,23 @@ class ARMAsmParser : public MCTargetAsmParser { ITState.CurPosition = ~0U; // Done with the IT block after this. } - - MCAsmParser &getParser() const { return Parser; } - MCAsmLexer &getLexer() const { return Parser.getLexer(); } - void Note(SMLoc L, const Twine &Msg, ArrayRef Ranges = None) { - return Parser.Note(L, Msg, Ranges); + return getParser().Note(L, Msg, Ranges); } bool Warning(SMLoc L, const Twine &Msg, ArrayRef Ranges = None) { - return Parser.Warning(L, Msg, Ranges); + return getParser().Warning(L, Msg, Ranges); } bool Error(SMLoc L, const Twine &Msg, ArrayRef Ranges = None) { - return Parser.Error(L, Msg, Ranges); + return getParser().Error(L, Msg, Ranges); } + bool validatetLDMRegList(const MCInst &Inst, const OperandVector &Operands, + unsigned ListNo, bool IsARPop = false); + bool validatetSTMRegList(const MCInst &Inst, const OperandVector &Operands, + unsigned ListNo); + int tryParseRegister(); bool tryParseRegisterWithWriteBack(OperandVector &); int tryParseShiftRegister(OperandVector &); @@ -237,41 +242,52 @@ class ARMAsmParser : public MCTargetAsmParser { bool &CanAcceptCarrySet, bool &CanAcceptPredicationCode); + void tryConvertingToTwoOperandForm(StringRef Mnemonic, bool CarrySetting, + OperandVector &Operands); bool isThumb() const { // FIXME: Can tablegen auto-generate this? - return (STI.getFeatureBits() & ARM::ModeThumb) != 0; + return STI.getFeatureBits()[ARM::ModeThumb]; } bool isThumbOne() const { - return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2) == 0; + return isThumb() && !STI.getFeatureBits()[ARM::FeatureThumb2]; } bool isThumbTwo() const { - return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2); + return isThumb() && STI.getFeatureBits()[ARM::FeatureThumb2]; } bool hasThumb() const { - return STI.getFeatureBits() & ARM::HasV4TOps; + return STI.getFeatureBits()[ARM::HasV4TOps]; } bool hasV6Ops() const { - return STI.getFeatureBits() & ARM::HasV6Ops; + return STI.getFeatureBits()[ARM::HasV6Ops]; } bool hasV6MOps() const { - return STI.getFeatureBits() & ARM::HasV6MOps; + return STI.getFeatureBits()[ARM::HasV6MOps]; } bool hasV7Ops() const { - return STI.getFeatureBits() & ARM::HasV7Ops; + return STI.getFeatureBits()[ARM::HasV7Ops]; } bool hasV8Ops() const { - return STI.getFeatureBits() & ARM::HasV8Ops; + return STI.getFeatureBits()[ARM::HasV8Ops]; } bool hasARM() const { - return !(STI.getFeatureBits() & ARM::FeatureNoARM); + return !STI.getFeatureBits()[ARM::FeatureNoARM]; + } + bool hasThumb2DSP() const { + return STI.getFeatureBits()[ARM::FeatureDSPThumb2]; + } + bool hasD16() const { + return STI.getFeatureBits()[ARM::FeatureD16]; + } + bool hasV8_1aOps() const { + return STI.getFeatureBits()[ARM::HasV8_1aOps]; } void SwitchMode() { - unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb)); + uint64_t FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb)); setAvailableFeatures(FB); } bool isMClass() const { - return STI.getFeatureBits() & ARM::FeatureMClass; + return STI.getFeatureBits()[ARM::FeatureMClass]; } /// @name Auto-generated Match Functions @@ -290,6 +306,7 @@ class ARMAsmParser : public MCTargetAsmParser { OperandMatchResultTy parseInstSyncBarrierOptOperand(OperandVector &); OperandMatchResultTy parseProcIFlagsOperand(OperandVector &); OperandMatchResultTy parseMSRMaskOperand(OperandVector &); + OperandMatchResultTy parseBankedRegOperand(OperandVector &); OperandMatchResultTy parsePKHImm(OperandVector &O, StringRef Op, int Low, int High); OperandMatchResultTy parsePKHLSLImm(OperandVector &O) { @@ -301,6 +318,7 @@ class ARMAsmParser : public MCTargetAsmParser { OperandMatchResultTy parseSetEndImm(OperandVector &); OperandMatchResultTy parseShifterImm(OperandVector &); OperandMatchResultTy parseRotImm(OperandVector &); + OperandMatchResultTy parseModImm(OperandVector &); OperandMatchResultTy parseBitfield(OperandVector &); OperandMatchResultTy parsePostIdxReg(OperandVector &); OperandMatchResultTy parseAM3Offset(OperandVector &); @@ -314,7 +332,7 @@ class ARMAsmParser : public MCTargetAsmParser { void cvtThumbBranches(MCInst &Inst, const OperandVector &); bool validateInstruction(MCInst &Inst, const OperandVector &Ops); - bool processInstruction(MCInst &Inst, const OperandVector &Ops); + bool processInstruction(MCInst &Inst, const OperandVector &Ops, MCStreamer &Out); bool shouldOmitCCOutOperand(StringRef Mnemonic, OperandVector &Operands); bool shouldOmitPredicateOperand(StringRef Mnemonic, OperandVector &Operands); @@ -329,11 +347,10 @@ public: }; - ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser, - const MCInstrInfo &MII, - const MCTargetOptions &Options) - : MCTargetAsmParser(), STI(_STI), Parser(_Parser), MII(MII), UC(_Parser) { - MCAsmParserExtension::Initialize(_Parser); + ARMAsmParser(MCSubtargetInfo &STI, MCAsmParser &Parser, + const MCInstrInfo &MII, const MCTargetOptions &Options) + : MCTargetAsmParser(Options), STI(STI), MII(MII), UC(Parser) { + MCAsmParserExtension::Initialize(Parser); // Cache the MCRegisterInfo. MRI = getContext().getRegisterInfo(); @@ -359,7 +376,7 @@ public: bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, OperandVector &Operands, MCStreamer &Out, - unsigned &ErrorInfo, + uint64_t &ErrorInfo, bool MatchingInlineAsm) override; void onLabelParsed(MCSymbol *Symbol) override; }; @@ -383,6 +400,7 @@ class ARMOperand : public MCParsedAsmOperand { k_Memory, k_PostIndexRegister, k_MSRMask, + k_BankedReg, k_ProcIFlags, k_VectorIndex, k_Register, @@ -396,6 +414,7 @@ class ARMOperand : public MCParsedAsmOperand { k_ShiftedImmediate, k_ShifterImmediate, k_RotateImmediate, + k_ModifiedImmediate, k_BitfieldDescriptor, k_Token } Kind; @@ -435,6 +454,10 @@ class ARMOperand : public MCParsedAsmOperand { unsigned Val; }; + struct BankedRegOp { + unsigned Val; + }; + struct TokOp { const char *Data; unsigned Length; @@ -503,6 +526,11 @@ class ARMOperand : public MCParsedAsmOperand { unsigned Imm; }; + struct ModImmOp { + unsigned Bits; + unsigned Rot; + }; + struct BitfieldOp { unsigned LSB; unsigned Width; @@ -517,6 +545,7 @@ class ARMOperand : public MCParsedAsmOperand { struct ITMaskOp ITMask; struct IFlagsOp IFlags; struct MMaskOp MMask; + struct BankedRegOp BankedReg; struct TokOp Tok; struct RegOp Reg; struct VectorListOp VectorList; @@ -528,86 +557,12 @@ class ARMOperand : public MCParsedAsmOperand { struct RegShiftedRegOp RegShiftedReg; struct RegShiftedImmOp RegShiftedImm; struct RotImmOp RotImm; + struct ModImmOp ModImm; struct BitfieldOp Bitfield; }; public: ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {} - ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() { - Kind = o.Kind; - StartLoc = o.StartLoc; - EndLoc = o.EndLoc; - switch (Kind) { - case k_CondCode: - CC = o.CC; - break; - case k_ITCondMask: - ITMask = o.ITMask; - break; - case k_Token: - Tok = o.Tok; - break; - case k_CCOut: - case k_Register: - Reg = o.Reg; - break; - case k_RegisterList: - case k_DPRRegisterList: - case k_SPRRegisterList: - Registers = o.Registers; - break; - case k_VectorList: - case k_VectorListAllLanes: - case k_VectorListIndexed: - VectorList = o.VectorList; - break; - case k_CoprocNum: - case k_CoprocReg: - Cop = o.Cop; - break; - case k_CoprocOption: - CoprocOption = o.CoprocOption; - break; - case k_Immediate: - Imm = o.Imm; - break; - case k_MemBarrierOpt: - MBOpt = o.MBOpt; - break; - case k_InstSyncBarrierOpt: - ISBOpt = o.ISBOpt; - case k_Memory: - Memory = o.Memory; - break; - case k_PostIndexRegister: - PostIdxReg = o.PostIdxReg; - break; - case k_MSRMask: - MMask = o.MMask; - break; - case k_ProcIFlags: - IFlags = o.IFlags; - break; - case k_ShifterImmediate: - ShifterImm = o.ShifterImm; - break; - case k_ShiftedRegister: - RegShiftedReg = o.RegShiftedReg; - break; - case k_ShiftedImmediate: - RegShiftedImm = o.RegShiftedImm; - break; - case k_RotateImmediate: - RotImm = o.RotImm; - break; - case k_BitfieldDescriptor: - Bitfield = o.Bitfield; - break; - case k_VectorIndex: - VectorIndex = o.VectorIndex; - break; - } - } /// getStartLoc - Get the location of the first token of this operand. SMLoc getStartLoc() const override { return StartLoc; } @@ -679,6 +634,11 @@ public: return MMask.Val; } + unsigned getBankedReg() const { + assert(Kind == k_BankedReg && "Invalid access!"); + return BankedReg.Val; + } + bool isCoprocNum() const { return Kind == k_CoprocNum; } bool isCoprocReg() const { return Kind == k_CoprocReg; } bool isCoprocOption() const { return Kind == k_CoprocOption; } @@ -1003,33 +963,17 @@ public: } bool isAdrLabel() const { // If we have an immediate that's not a constant, treat it as a label - // reference needing a fixup. If it is a constant, but it can't fit - // into shift immediate encoding, we reject it. - if (isImm() && !isa(getImm())) return true; - else return (isARMSOImm() || isARMSOImmNeg()); - } - bool isARMSOImm() const { - if (!isImm()) return false; - const MCConstantExpr *CE = dyn_cast(getImm()); - if (!CE) return false; - int64_t Value = CE->getValue(); - return ARM_AM::getSOImmVal(Value) != -1; - } - bool isARMSOImmNot() const { - if (!isImm()) return false; - const MCConstantExpr *CE = dyn_cast(getImm()); - if (!CE) return false; - int64_t Value = CE->getValue(); - return ARM_AM::getSOImmVal(~Value) != -1; - } - bool isARMSOImmNeg() const { + // reference needing a fixup. + if (isImm() && !isa(getImm())) + return true; + + // If it is a constant, it must fit into a modified immediate encoding. if (!isImm()) return false; const MCConstantExpr *CE = dyn_cast(getImm()); if (!CE) return false; int64_t Value = CE->getValue(); - // Only use this when not representable as a plain so_imm. - return ARM_AM::getSOImmVal(Value) == -1 && - ARM_AM::getSOImmVal(-Value) != -1; + return (ARM_AM::getSOImmVal(Value) != -1 || + ARM_AM::getSOImmVal(-Value) != -1); } bool isT2SOImm() const { if (!isImm()) return false; @@ -1074,6 +1018,22 @@ public: bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; } bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; } bool isRotImm() const { return Kind == k_RotateImmediate; } + bool isModImm() const { return Kind == k_ModifiedImmediate; } + bool isModImmNot() const { + if (!isImm()) return false; + const MCConstantExpr *CE = dyn_cast(getImm()); + if (!CE) return false; + int64_t Value = CE->getValue(); + return ARM_AM::getSOImmVal(~Value) != -1; + } + bool isModImmNeg() const { + if (!isImm()) return false; + const MCConstantExpr *CE = dyn_cast(getImm()); + if (!CE) return false; + int64_t Value = CE->getValue(); + return ARM_AM::getSOImmVal(Value) == -1 && + ARM_AM::getSOImmVal(-Value) != -1; + } bool isBitfield() const { return Kind == k_BitfieldDescriptor; } bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; } bool isPostIdxReg() const { @@ -1384,6 +1344,7 @@ public: } bool isMSRMask() const { return Kind == k_MSRMask; } + bool isBankedReg() const { return Kind == k_BankedReg; } bool isProcIFlags() const { return Kind == k_ProcIFlags; } // NEON operands. @@ -1601,9 +1562,18 @@ public: const MCConstantExpr *CE = dyn_cast(getImm()); // Must be a constant. if (!CE) return false; - int64_t Value = CE->getValue(); - // i16 value in the range [0,255] or [0x0100, 0xff00] - return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00); + unsigned Value = CE->getValue(); + return ARM_AM::isNEONi16splat(Value); + } + + bool isNEONi16splatNot() const { + if (!isImm()) + return false; + const MCConstantExpr *CE = dyn_cast(getImm()); + // Must be a constant. + if (!CE) return false; + unsigned Value = CE->getValue(); + return ARM_AM::isNEONi16splat(~Value & 0xffff); } bool isNEONi32splat() const { @@ -1614,12 +1584,18 @@ public: const MCConstantExpr *CE = dyn_cast(getImm()); // Must be a constant. if (!CE) return false; - int64_t Value = CE->getValue(); - // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X. - return (Value >= 0 && Value < 256) || - (Value >= 0x0100 && Value <= 0xff00) || - (Value >= 0x010000 && Value <= 0xff0000) || - (Value >= 0x01000000 && Value <= 0xff000000); + unsigned Value = CE->getValue(); + return ARM_AM::isNEONi32splat(Value); + } + + bool isNEONi32splatNot() const { + if (!isImm()) + return false; + const MCConstantExpr *CE = dyn_cast(getImm()); + // Must be a constant. + if (!CE) return false; + unsigned Value = CE->getValue(); + return ARM_AM::isNEONi32splat(~Value); } bool isNEONByteReplicate(unsigned NumBytes) const { @@ -1655,6 +1631,7 @@ public: int64_t Value = CE->getValue(); // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X, // for VMOV/VMVN only, 00Xf or 0Xff are also accepted. + // FIXME: This is probably wrong and a copy and paste from previous example return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00) || (Value >= 0x010000 && Value <= 0xff0000) || @@ -1670,6 +1647,7 @@ public: int64_t Value = ~CE->getValue(); // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X, // for VMOV/VMVN only, 00Xf or 0Xff are also accepted. + // FIXME: This is probably wrong and a copy and paste from previous example return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00) || (Value >= 0x010000 && Value <= 0xff0000) || @@ -1693,62 +1671,62 @@ public: void addExpr(MCInst &Inst, const MCExpr *Expr) const { // Add as immediates when possible. Null MCExpr = 0. if (!Expr) - Inst.addOperand(MCOperand::CreateImm(0)); + Inst.addOperand(MCOperand::createImm(0)); else if (const MCConstantExpr *CE = dyn_cast(Expr)) - Inst.addOperand(MCOperand::CreateImm(CE->getValue())); + Inst.addOperand(MCOperand::createImm(CE->getValue())); else - Inst.addOperand(MCOperand::CreateExpr(Expr)); + Inst.addOperand(MCOperand::createExpr(Expr)); } void addCondCodeOperands(MCInst &Inst, unsigned N) const { assert(N == 2 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode()))); + Inst.addOperand(MCOperand::createImm(unsigned(getCondCode()))); unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR; - Inst.addOperand(MCOperand::CreateReg(RegNum)); + Inst.addOperand(MCOperand::createReg(RegNum)); } void addCoprocNumOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateImm(getCoproc())); + Inst.addOperand(MCOperand::createImm(getCoproc())); } void addCoprocRegOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateImm(getCoproc())); + Inst.addOperand(MCOperand::createImm(getCoproc())); } void addCoprocOptionOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val)); + Inst.addOperand(MCOperand::createImm(CoprocOption.Val)); } void addITMaskOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateImm(ITMask.Mask)); + Inst.addOperand(MCOperand::createImm(ITMask.Mask)); } void addITCondCodeOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode()))); + Inst.addOperand(MCOperand::createImm(unsigned(getCondCode()))); } void addCCOutOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateReg(getReg())); + Inst.addOperand(MCOperand::createReg(getReg())); } void addRegOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateReg(getReg())); + Inst.addOperand(MCOperand::createReg(getReg())); } void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const { assert(N == 3 && "Invalid number of operands!"); assert(isRegShiftedReg() && "addRegShiftedRegOperands() on non-RegShiftedReg!"); - Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg)); - Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg)); - Inst.addOperand(MCOperand::CreateImm( + Inst.addOperand(MCOperand::createReg(RegShiftedReg.SrcReg)); + Inst.addOperand(MCOperand::createReg(RegShiftedReg.ShiftReg)); + Inst.addOperand(MCOperand::createImm( ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm))); } @@ -1756,16 +1734,16 @@ public: assert(N == 2 && "Invalid number of operands!"); assert(isRegShiftedImm() && "addRegShiftedImmOperands() on non-RegShiftedImm!"); - Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg)); + Inst.addOperand(MCOperand::createReg(RegShiftedImm.SrcReg)); // Shift of #32 is encoded as 0 where permitted unsigned Imm = (RegShiftedImm.ShiftImm == 32 ? 0 : RegShiftedImm.ShiftImm); - Inst.addOperand(MCOperand::CreateImm( + Inst.addOperand(MCOperand::createImm( ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, Imm))); } void addShifterImmOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) | + Inst.addOperand(MCOperand::createImm((ShifterImm.isASR << 5) | ShifterImm.Imm)); } @@ -1774,7 +1752,7 @@ public: const SmallVectorImpl &RegList = getRegList(); for (SmallVectorImpl::const_iterator I = RegList.begin(), E = RegList.end(); I != E; ++I) - Inst.addOperand(MCOperand::CreateReg(*I)); + Inst.addOperand(MCOperand::createReg(*I)); } void addDPRRegListOperands(MCInst &Inst, unsigned N) const { @@ -1788,7 +1766,31 @@ public: void addRotImmOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); // Encoded as val>>3. The printer handles display as 8, 16, 24. - Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3)); + Inst.addOperand(MCOperand::createImm(RotImm.Imm >> 3)); + } + + void addModImmOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + + // Support for fixups (MCFixup) + if (isImm()) + return addImmOperands(Inst, N); + + Inst.addOperand(MCOperand::createImm(ModImm.Bits | (ModImm.Rot << 7))); + } + + void addModImmNotOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + const MCConstantExpr *CE = dyn_cast(getImm()); + uint32_t Enc = ARM_AM::getSOImmVal(~CE->getValue()); + Inst.addOperand(MCOperand::createImm(Enc)); + } + + void addModImmNegOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + const MCConstantExpr *CE = dyn_cast(getImm()); + uint32_t Enc = ARM_AM::getSOImmVal(-CE->getValue()); + Inst.addOperand(MCOperand::createImm(Enc)); } void addBitfieldOperands(MCInst &Inst, unsigned N) const { @@ -1799,7 +1801,7 @@ public: // Make a 32-bit mask w/ the referenced bits clear and all other bits set. uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >> (32 - (lsb + width))); - Inst.addOperand(MCOperand::CreateImm(Mask)); + Inst.addOperand(MCOperand::createImm(Mask)); } void addImmOperands(MCInst &Inst, unsigned N) const { @@ -1810,20 +1812,20 @@ public: void addFBits16Operands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); const MCConstantExpr *CE = dyn_cast(getImm()); - Inst.addOperand(MCOperand::CreateImm(16 - CE->getValue())); + Inst.addOperand(MCOperand::createImm(16 - CE->getValue())); } void addFBits32Operands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); const MCConstantExpr *CE = dyn_cast(getImm()); - Inst.addOperand(MCOperand::CreateImm(32 - CE->getValue())); + Inst.addOperand(MCOperand::createImm(32 - CE->getValue())); } void addFPImmOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); const MCConstantExpr *CE = dyn_cast(getImm()); int Val = ARM_AM::getFP32Imm(APInt(32, CE->getValue())); - Inst.addOperand(MCOperand::CreateImm(Val)); + Inst.addOperand(MCOperand::createImm(Val)); } void addImm8s4Operands(MCInst &Inst, unsigned N) const { @@ -1831,7 +1833,7 @@ public: // FIXME: We really want to scale the value here, but the LDRD/STRD // instruction don't encode operands that way yet. const MCConstantExpr *CE = dyn_cast(getImm()); - Inst.addOperand(MCOperand::CreateImm(CE->getValue())); + Inst.addOperand(MCOperand::createImm(CE->getValue())); } void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const { @@ -1839,7 +1841,7 @@ public: // The immediate is scaled by four in the encoding and is stored // in the MCInst as such. Lop off the low two bits here. const MCConstantExpr *CE = dyn_cast(getImm()); - Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4)); + Inst.addOperand(MCOperand::createImm(CE->getValue() / 4)); } void addImm0_508s4NegOperands(MCInst &Inst, unsigned N) const { @@ -1847,7 +1849,7 @@ public: // The immediate is scaled by four in the encoding and is stored // in the MCInst as such. Lop off the low two bits here. const MCConstantExpr *CE = dyn_cast(getImm()); - Inst.addOperand(MCOperand::CreateImm(-(CE->getValue() / 4))); + Inst.addOperand(MCOperand::createImm(-(CE->getValue() / 4))); } void addImm0_508s4Operands(MCInst &Inst, unsigned N) const { @@ -1855,7 +1857,7 @@ public: // The immediate is scaled by four in the encoding and is stored // in the MCInst as such. Lop off the low two bits here. const MCConstantExpr *CE = dyn_cast(getImm()); - Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4)); + Inst.addOperand(MCOperand::createImm(CE->getValue() / 4)); } void addImm1_16Operands(MCInst &Inst, unsigned N) const { @@ -1863,7 +1865,7 @@ public: // The constant encodes as the immediate-1, and we store in the instruction // the bits as encoded, so subtract off one here. const MCConstantExpr *CE = dyn_cast(getImm()); - Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1)); + Inst.addOperand(MCOperand::createImm(CE->getValue() - 1)); } void addImm1_32Operands(MCInst &Inst, unsigned N) const { @@ -1871,7 +1873,7 @@ public: // The constant encodes as the immediate-1, and we store in the instruction // the bits as encoded, so subtract off one here. const MCConstantExpr *CE = dyn_cast(getImm()); - Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1)); + Inst.addOperand(MCOperand::createImm(CE->getValue() - 1)); } void addImmThumbSROperands(MCInst &Inst, unsigned N) const { @@ -1880,7 +1882,7 @@ public: // zero. const MCConstantExpr *CE = dyn_cast(getImm()); unsigned Imm = CE->getValue(); - Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm))); + Inst.addOperand(MCOperand::createImm((Imm == 32 ? 0 : Imm))); } void addPKHASRImmOperands(MCInst &Inst, unsigned N) const { @@ -1889,7 +1891,7 @@ public: // the instruction as well. const MCConstantExpr *CE = dyn_cast(getImm()); int Val = CE->getValue(); - Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val)); + Inst.addOperand(MCOperand::createImm(Val == 32 ? 0 : Val)); } void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const { @@ -1897,7 +1899,7 @@ public: // The operand is actually a t2_so_imm, but we have its bitwise // negation in the assembly source, so twiddle it here. const MCConstantExpr *CE = dyn_cast(getImm()); - Inst.addOperand(MCOperand::CreateImm(~CE->getValue())); + Inst.addOperand(MCOperand::createImm(~CE->getValue())); } void addT2SOImmNegOperands(MCInst &Inst, unsigned N) const { @@ -1905,7 +1907,7 @@ public: // The operand is actually a t2_so_imm, but we have its // negation in the assembly source, so twiddle it here. const MCConstantExpr *CE = dyn_cast(getImm()); - Inst.addOperand(MCOperand::CreateImm(-CE->getValue())); + Inst.addOperand(MCOperand::createImm(-CE->getValue())); } void addImm0_4095NegOperands(MCInst &Inst, unsigned N) const { @@ -1913,18 +1915,18 @@ public: // The operand is actually an imm0_4095, but we have its // negation in the assembly source, so twiddle it here. const MCConstantExpr *CE = dyn_cast(getImm()); - Inst.addOperand(MCOperand::CreateImm(-CE->getValue())); + Inst.addOperand(MCOperand::createImm(-CE->getValue())); } void addUnsignedOffset_b8s2Operands(MCInst &Inst, unsigned N) const { if(const MCConstantExpr *CE = dyn_cast(getImm())) { - Inst.addOperand(MCOperand::CreateImm(CE->getValue() >> 2)); + Inst.addOperand(MCOperand::createImm(CE->getValue() >> 2)); return; } const MCSymbolRefExpr *SR = dyn_cast(Imm.Val); assert(SR && "Unknown value type!"); - Inst.addOperand(MCOperand::CreateExpr(SR)); + Inst.addOperand(MCOperand::createExpr(SR)); } void addThumbMemPCOperands(MCInst &Inst, unsigned N) const { @@ -1932,56 +1934,40 @@ public: if (isImm()) { const MCConstantExpr *CE = dyn_cast(getImm()); if (CE) { - Inst.addOperand(MCOperand::CreateImm(CE->getValue())); + Inst.addOperand(MCOperand::createImm(CE->getValue())); return; } const MCSymbolRefExpr *SR = dyn_cast(Imm.Val); assert(SR && "Unknown value type!"); - Inst.addOperand(MCOperand::CreateExpr(SR)); + Inst.addOperand(MCOperand::createExpr(SR)); return; } assert(isMem() && "Unknown value type!"); assert(isa(Memory.OffsetImm) && "Unknown value type!"); - Inst.addOperand(MCOperand::CreateImm(Memory.OffsetImm->getValue())); - } - - void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const { - assert(N == 1 && "Invalid number of operands!"); - // The operand is actually a so_imm, but we have its bitwise - // negation in the assembly source, so twiddle it here. - const MCConstantExpr *CE = dyn_cast(getImm()); - Inst.addOperand(MCOperand::CreateImm(~CE->getValue())); - } - - void addARMSOImmNegOperands(MCInst &Inst, unsigned N) const { - assert(N == 1 && "Invalid number of operands!"); - // The operand is actually a so_imm, but we have its - // negation in the assembly source, so twiddle it here. - const MCConstantExpr *CE = dyn_cast(getImm()); - Inst.addOperand(MCOperand::CreateImm(-CE->getValue())); + Inst.addOperand(MCOperand::createImm(Memory.OffsetImm->getValue())); } void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt()))); + Inst.addOperand(MCOperand::createImm(unsigned(getMemBarrierOpt()))); } void addInstSyncBarrierOptOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateImm(unsigned(getInstSyncBarrierOpt()))); + Inst.addOperand(MCOperand::createImm(unsigned(getInstSyncBarrierOpt()))); } void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); + Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); } void addMemPCRelImm12Operands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); int32_t Imm = Memory.OffsetImm->getValue(); - Inst.addOperand(MCOperand::CreateImm(Imm)); + Inst.addOperand(MCOperand::createImm(Imm)); } void addAdrLabelOperands(MCInst &Inst, unsigned N) const { @@ -1991,19 +1977,19 @@ public: // If we have an immediate that's not a constant, treat it as a label // reference needing a fixup. if (!isa(getImm())) { - Inst.addOperand(MCOperand::CreateExpr(getImm())); + Inst.addOperand(MCOperand::createExpr(getImm())); return; } const MCConstantExpr *CE = dyn_cast(getImm()); int Val = CE->getValue(); - Inst.addOperand(MCOperand::CreateImm(Val)); + Inst.addOperand(MCOperand::createImm(Val)); } void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const { assert(N == 2 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); - Inst.addOperand(MCOperand::CreateImm(Memory.Alignment)); + Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); + Inst.addOperand(MCOperand::createImm(Memory.Alignment)); } void addDupAlignedMemoryNoneOperands(MCInst &Inst, unsigned N) const { @@ -2065,9 +2051,9 @@ public: Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, Memory.ShiftImm, Memory.ShiftType); } - Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); - Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum)); - Inst.addOperand(MCOperand::CreateImm(Val)); + Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); + Inst.addOperand(MCOperand::createReg(Memory.OffsetRegNum)); + Inst.addOperand(MCOperand::createImm(Val)); } void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const { @@ -2080,8 +2066,8 @@ public: if (Val == INT32_MIN) Val = 0; if (Val < 0) Val = -Val; Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift); - Inst.addOperand(MCOperand::CreateReg(0)); - Inst.addOperand(MCOperand::CreateImm(Val)); + Inst.addOperand(MCOperand::createReg(0)); + Inst.addOperand(MCOperand::createImm(Val)); } void addAddrMode3Operands(MCInst &Inst, unsigned N) const { @@ -2090,9 +2076,9 @@ public: // reference needing a fixup. If it is a constant, it's something else // and we reject it. if (isImm()) { - Inst.addOperand(MCOperand::CreateExpr(getImm())); - Inst.addOperand(MCOperand::CreateReg(0)); - Inst.addOperand(MCOperand::CreateImm(0)); + Inst.addOperand(MCOperand::createExpr(getImm())); + Inst.addOperand(MCOperand::createReg(0)); + Inst.addOperand(MCOperand::createImm(0)); return; } @@ -2108,9 +2094,9 @@ public: // here. Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0); } - Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); - Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum)); - Inst.addOperand(MCOperand::CreateImm(Val)); + Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); + Inst.addOperand(MCOperand::createReg(Memory.OffsetRegNum)); + Inst.addOperand(MCOperand::createImm(Val)); } void addAM3OffsetOperands(MCInst &Inst, unsigned N) const { @@ -2118,8 +2104,8 @@ public: if (Kind == k_PostIndexRegister) { int32_t Val = ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0); - Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum)); - Inst.addOperand(MCOperand::CreateImm(Val)); + Inst.addOperand(MCOperand::createReg(PostIdxReg.RegNum)); + Inst.addOperand(MCOperand::createImm(Val)); return; } @@ -2131,8 +2117,8 @@ public: if (Val == INT32_MIN) Val = 0; if (Val < 0) Val = -Val; Val = ARM_AM::getAM3Opc(AddSub, Val); - Inst.addOperand(MCOperand::CreateReg(0)); - Inst.addOperand(MCOperand::CreateImm(Val)); + Inst.addOperand(MCOperand::createReg(0)); + Inst.addOperand(MCOperand::createImm(Val)); } void addAddrMode5Operands(MCInst &Inst, unsigned N) const { @@ -2141,8 +2127,8 @@ public: // reference needing a fixup. If it is a constant, it's something else // and we reject it. if (isImm()) { - Inst.addOperand(MCOperand::CreateExpr(getImm())); - Inst.addOperand(MCOperand::CreateImm(0)); + Inst.addOperand(MCOperand::createExpr(getImm())); + Inst.addOperand(MCOperand::createImm(0)); return; } @@ -2153,8 +2139,8 @@ public: if (Val == INT32_MIN) Val = 0; if (Val < 0) Val = -Val; Val = ARM_AM::getAM5Opc(AddSub, Val); - Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); - Inst.addOperand(MCOperand::CreateImm(Val)); + Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); + Inst.addOperand(MCOperand::createImm(Val)); } void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const { @@ -2163,29 +2149,29 @@ public: // reference needing a fixup. If it is a constant, it's something else // and we reject it. if (isImm()) { - Inst.addOperand(MCOperand::CreateExpr(getImm())); - Inst.addOperand(MCOperand::CreateImm(0)); + Inst.addOperand(MCOperand::createExpr(getImm())); + Inst.addOperand(MCOperand::createImm(0)); return; } int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0; - Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); - Inst.addOperand(MCOperand::CreateImm(Val)); + Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); + Inst.addOperand(MCOperand::createImm(Val)); } void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const { assert(N == 2 && "Invalid number of operands!"); // The lower two bits are always zero and as such are not encoded. int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0; - Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); - Inst.addOperand(MCOperand::CreateImm(Val)); + Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); + Inst.addOperand(MCOperand::createImm(Val)); } void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const { assert(N == 2 && "Invalid number of operands!"); int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0; - Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); - Inst.addOperand(MCOperand::CreateImm(Val)); + Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); + Inst.addOperand(MCOperand::createImm(Val)); } void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const { @@ -2201,14 +2187,14 @@ public: // If this is an immediate, it's a label reference. if (isImm()) { addExpr(Inst, getImm()); - Inst.addOperand(MCOperand::CreateImm(0)); + Inst.addOperand(MCOperand::createImm(0)); return; } // Otherwise, it's a normal memory reg+offset. int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0; - Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); - Inst.addOperand(MCOperand::CreateImm(Val)); + Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); + Inst.addOperand(MCOperand::createImm(Val)); } void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const { @@ -2216,26 +2202,26 @@ public: // If this is an immediate, it's a label reference. if (isImm()) { addExpr(Inst, getImm()); - Inst.addOperand(MCOperand::CreateImm(0)); + Inst.addOperand(MCOperand::createImm(0)); return; } // Otherwise, it's a normal memory reg+offset. int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0; - Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); - Inst.addOperand(MCOperand::CreateImm(Val)); + Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); + Inst.addOperand(MCOperand::createImm(Val)); } void addMemTBBOperands(MCInst &Inst, unsigned N) const { assert(N == 2 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); - Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum)); + Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); + Inst.addOperand(MCOperand::createReg(Memory.OffsetRegNum)); } void addMemTBHOperands(MCInst &Inst, unsigned N) const { assert(N == 2 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); - Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum)); + Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); + Inst.addOperand(MCOperand::createReg(Memory.OffsetRegNum)); } void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const { @@ -2243,50 +2229,50 @@ public: unsigned Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, Memory.ShiftImm, Memory.ShiftType); - Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); - Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum)); - Inst.addOperand(MCOperand::CreateImm(Val)); + Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); + Inst.addOperand(MCOperand::createReg(Memory.OffsetRegNum)); + Inst.addOperand(MCOperand::createImm(Val)); } void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const { assert(N == 3 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); - Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum)); - Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm)); + Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); + Inst.addOperand(MCOperand::createReg(Memory.OffsetRegNum)); + Inst.addOperand(MCOperand::createImm(Memory.ShiftImm)); } void addMemThumbRROperands(MCInst &Inst, unsigned N) const { assert(N == 2 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); - Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum)); + Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); + Inst.addOperand(MCOperand::createReg(Memory.OffsetRegNum)); } void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const { assert(N == 2 && "Invalid number of operands!"); int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0; - Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); - Inst.addOperand(MCOperand::CreateImm(Val)); + Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); + Inst.addOperand(MCOperand::createImm(Val)); } void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const { assert(N == 2 && "Invalid number of operands!"); int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0; - Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); - Inst.addOperand(MCOperand::CreateImm(Val)); + Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); + Inst.addOperand(MCOperand::createImm(Val)); } void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const { assert(N == 2 && "Invalid number of operands!"); int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0; - Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); - Inst.addOperand(MCOperand::CreateImm(Val)); + Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); + Inst.addOperand(MCOperand::createImm(Val)); } void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const { assert(N == 2 && "Invalid number of operands!"); int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0; - Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); - Inst.addOperand(MCOperand::CreateImm(Val)); + Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); + Inst.addOperand(MCOperand::createImm(Val)); } void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const { @@ -2297,7 +2283,7 @@ public: bool isAdd = Imm >= 0; if (Imm == INT32_MIN) Imm = 0; Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8; - Inst.addOperand(MCOperand::CreateImm(Imm)); + Inst.addOperand(MCOperand::createImm(Imm)); } void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const { @@ -2309,60 +2295,65 @@ public: if (Imm == INT32_MIN) Imm = 0; // Immediate is scaled by 4. Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8; - Inst.addOperand(MCOperand::CreateImm(Imm)); + Inst.addOperand(MCOperand::createImm(Imm)); } void addPostIdxRegOperands(MCInst &Inst, unsigned N) const { assert(N == 2 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum)); - Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd)); + Inst.addOperand(MCOperand::createReg(PostIdxReg.RegNum)); + Inst.addOperand(MCOperand::createImm(PostIdxReg.isAdd)); } void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const { assert(N == 2 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum)); + Inst.addOperand(MCOperand::createReg(PostIdxReg.RegNum)); // The sign, shift type, and shift amount are encoded in a single operand // using the AM2 encoding helpers. ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub; unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm, PostIdxReg.ShiftTy); - Inst.addOperand(MCOperand::CreateImm(Imm)); + Inst.addOperand(MCOperand::createImm(Imm)); } void addMSRMaskOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask()))); + Inst.addOperand(MCOperand::createImm(unsigned(getMSRMask()))); + } + + void addBankedRegOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + Inst.addOperand(MCOperand::createImm(unsigned(getBankedReg()))); } void addProcIFlagsOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags()))); + Inst.addOperand(MCOperand::createImm(unsigned(getProcIFlags()))); } void addVecListOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum)); + Inst.addOperand(MCOperand::createReg(VectorList.RegNum)); } void addVecListIndexedOperands(MCInst &Inst, unsigned N) const { assert(N == 2 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum)); - Inst.addOperand(MCOperand::CreateImm(VectorList.LaneIndex)); + Inst.addOperand(MCOperand::createReg(VectorList.RegNum)); + Inst.addOperand(MCOperand::createImm(VectorList.LaneIndex)); } void addVectorIndex8Operands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateImm(getVectorIndex())); + Inst.addOperand(MCOperand::createImm(getVectorIndex())); } void addVectorIndex16Operands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateImm(getVectorIndex())); + Inst.addOperand(MCOperand::createImm(getVectorIndex())); } void addVectorIndex32Operands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateImm(getVectorIndex())); + Inst.addOperand(MCOperand::createImm(getVectorIndex())); } void addNEONi8splatOperands(MCInst &Inst, unsigned N) const { @@ -2370,7 +2361,7 @@ public: // The immediate encodes the type of constant as well as the value. // Mask in that this is an i8 splat. const MCConstantExpr *CE = dyn_cast(getImm()); - Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00)); + Inst.addOperand(MCOperand::createImm(CE->getValue() | 0xe00)); } void addNEONi16splatOperands(MCInst &Inst, unsigned N) const { @@ -2378,11 +2369,17 @@ public: // The immediate encodes the type of constant as well as the value. const MCConstantExpr *CE = dyn_cast(getImm()); unsigned Value = CE->getValue(); - if (Value >= 256) - Value = (Value >> 8) | 0xa00; - else - Value |= 0x800; - Inst.addOperand(MCOperand::CreateImm(Value)); + Value = ARM_AM::encodeNEONi16splat(Value); + Inst.addOperand(MCOperand::createImm(Value)); + } + + void addNEONi16splatNotOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + // The immediate encodes the type of constant as well as the value. + const MCConstantExpr *CE = dyn_cast(getImm()); + unsigned Value = CE->getValue(); + Value = ARM_AM::encodeNEONi16splat(~Value & 0xffff); + Inst.addOperand(MCOperand::createImm(Value)); } void addNEONi32splatOperands(MCInst &Inst, unsigned N) const { @@ -2390,13 +2387,17 @@ public: // The immediate encodes the type of constant as well as the value. const MCConstantExpr *CE = dyn_cast(getImm()); unsigned Value = CE->getValue(); - if (Value >= 256 && Value <= 0xff00) - Value = (Value >> 8) | 0x200; - else if (Value > 0xffff && Value <= 0xff0000) - Value = (Value >> 16) | 0x400; - else if (Value > 0xffffff) - Value = (Value >> 24) | 0x600; - Inst.addOperand(MCOperand::CreateImm(Value)); + Value = ARM_AM::encodeNEONi32splat(Value); + Inst.addOperand(MCOperand::createImm(Value)); + } + + void addNEONi32splatNotOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + // The immediate encodes the type of constant as well as the value. + const MCConstantExpr *CE = dyn_cast(getImm()); + unsigned Value = CE->getValue(); + Value = ARM_AM::encodeNEONi32splat(~Value); + Inst.addOperand(MCOperand::createImm(Value)); } void addNEONinvByteReplicateOperands(MCInst &Inst, unsigned N) const { @@ -2410,7 +2411,7 @@ public: "always must be replaced with VMOVv8i8 or VMOVv16i8."); unsigned B = ((~Value) & 0xff); B |= 0xe00; // cmode = 0b1110 - Inst.addOperand(MCOperand::CreateImm(B)); + Inst.addOperand(MCOperand::createImm(B)); } void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); @@ -2423,7 +2424,7 @@ public: Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400); else if (Value > 0xffffff) Value = (Value >> 24) | 0x600; - Inst.addOperand(MCOperand::CreateImm(Value)); + Inst.addOperand(MCOperand::createImm(Value)); } void addNEONvmovByteReplicateOperands(MCInst &Inst, unsigned N) const { @@ -2437,7 +2438,7 @@ public: "always must be replaced with VMOVv8i8 or VMOVv16i8."); unsigned B = Value & 0xff; B |= 0xe00; // cmode = 0b1110 - Inst.addOperand(MCOperand::CreateImm(B)); + Inst.addOperand(MCOperand::createImm(B)); } void addNEONi32vmovNegOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); @@ -2450,7 +2451,7 @@ public: Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400); else if (Value > 0xffffff) Value = (Value >> 24) | 0x600; - Inst.addOperand(MCOperand::CreateImm(Value)); + Inst.addOperand(MCOperand::createImm(Value)); } void addNEONi64splatOperands(MCInst &Inst, unsigned N) const { @@ -2462,7 +2463,7 @@ public: for (unsigned i = 0; i < 8; ++i, Value >>= 8) { Imm |= (Value & 1) << i; } - Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00)); + Inst.addOperand(MCOperand::createImm(Imm | 0x1e00)); } void print(raw_ostream &OS) const override; @@ -2580,6 +2581,16 @@ public: return Op; } + static std::unique_ptr CreateModImm(unsigned Bits, unsigned Rot, + SMLoc S, SMLoc E) { + auto Op = make_unique(k_ModifiedImmediate); + Op->ModImm.Bits = Bits; + Op->ModImm.Rot = Rot; + Op->StartLoc = S; + Op->EndLoc = E; + return Op; + } + static std::unique_ptr CreateBitfield(unsigned LSB, unsigned Width, SMLoc S, SMLoc E) { auto Op = make_unique(k_BitfieldDescriptor); @@ -2736,6 +2747,14 @@ public: Op->EndLoc = S; return Op; } + + static std::unique_ptr CreateBankedReg(unsigned Reg, SMLoc S) { + auto Op = make_unique(k_BankedReg); + Op->BankedReg.Val = Reg; + Op->StartLoc = S; + Op->EndLoc = S; + return Op; + } }; } // end anonymous namespace. @@ -2769,8 +2788,11 @@ void ARMOperand::print(raw_ostream &OS) const { case k_MSRMask: OS << ""; break; + case k_BankedReg: + OS << ""; + break; case k_Immediate: - getImm()->print(OS); + OS << *getImm(); break; case k_MemBarrierOpt: OS << ""; @@ -2822,6 +2844,10 @@ void ARMOperand::print(raw_ostream &OS) const { case k_RotateImmediate: OS << ""; break; + case k_ModifiedImmediate: + OS << ""; + break; case k_BitfieldDescriptor: OS << ""; @@ -2871,8 +2897,9 @@ static unsigned MatchRegisterName(StringRef Name); bool ARMAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) { - StartLoc = Parser.getTok().getLoc(); - EndLoc = Parser.getTok().getEndLoc(); + const AsmToken &Tok = getParser().getTok(); + StartLoc = Tok.getLoc(); + EndLoc = Tok.getEndLoc(); RegNo = tryParseRegister(); return (RegNo == (unsigned)-1); @@ -2883,6 +2910,7 @@ bool ARMAsmParser::ParseRegister(unsigned &RegNo, /// returned. Otherwise return -1. /// int ARMAsmParser::tryParseRegister() { + MCAsmParser &Parser = getParser(); const AsmToken &Tok = Parser.getTok(); if (Tok.isNot(AsmToken::Identifier)) return -1; @@ -2924,6 +2952,10 @@ int ARMAsmParser::tryParseRegister() { return Entry->getValue(); } + // Some FPUs only have 16 D registers, so D16-D31 are invalid + if (hasD16() && RegNum >= ARM::D16 && RegNum <= ARM::D31) + return -1; + Parser.Lex(); // Eat identifier token. return RegNum; @@ -2935,6 +2967,7 @@ int ARMAsmParser::tryParseRegister() { // consumed in the process of trying to parse the shifter (i.e., when it is // indeed a shifter operand, but malformed). int ARMAsmParser::tryParseShiftRegister(OperandVector &Operands) { + MCAsmParser &Parser = getParser(); SMLoc S = Parser.getTok().getLoc(); const AsmToken &Tok = Parser.getTok(); if (Tok.isNot(AsmToken::Identifier)) @@ -3037,6 +3070,7 @@ int ARMAsmParser::tryParseShiftRegister(OperandVector &Operands) { /// TODO this is likely to change to allow different register types and or to /// parse for a specific register type. bool ARMAsmParser::tryParseRegisterWithWriteBack(OperandVector &Operands) { + MCAsmParser &Parser = getParser(); const AsmToken &RegTok = Parser.getTok(); int RegNo = tryParseRegister(); if (RegNo == -1) @@ -3118,9 +3152,10 @@ static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) { return -1; switch (Name[1]) { default: return -1; - // p10 and p11 are invalid for coproc instructions (reserved for FP/NEON) - case '0': return CoprocOp == 'p'? -1: 10; - case '1': return CoprocOp == 'p'? -1: 11; + // CP10 and CP11 are VFP/NEON and so vector instructions should be used. + // However, old cores (v5/v6) did use them in that way. + case '0': return 10; + case '1': return 11; case '2': return 12; case '3': return 13; case '4': return 14; @@ -3132,6 +3167,7 @@ static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) { /// parseITCondCode - Try to parse a condition code for an IT instruction. ARMAsmParser::OperandMatchResultTy ARMAsmParser::parseITCondCode(OperandVector &Operands) { + MCAsmParser &Parser = getParser(); SMLoc S = Parser.getTok().getLoc(); const AsmToken &Tok = Parser.getTok(); if (!Tok.is(AsmToken::Identifier)) @@ -3169,6 +3205,7 @@ ARMAsmParser::parseITCondCode(OperandVector &Operands) { /// number, the token is eaten and the operand is added to the operand list. ARMAsmParser::OperandMatchResultTy ARMAsmParser::parseCoprocNumOperand(OperandVector &Operands) { + MCAsmParser &Parser = getParser(); SMLoc S = Parser.getTok().getLoc(); const AsmToken &Tok = Parser.getTok(); if (Tok.isNot(AsmToken::Identifier)) @@ -3177,6 +3214,9 @@ ARMAsmParser::parseCoprocNumOperand(OperandVector &Operands) { int Num = MatchCoprocessorOperandName(Tok.getString(), 'p'); if (Num == -1) return MatchOperand_NoMatch; + // ARMv7 and v8 don't allow cp10/cp11 due to VFP/NEON specific instructions + if ((hasV7Ops() || hasV8Ops()) && (Num == 10 || Num == 11)) + return MatchOperand_NoMatch; Parser.Lex(); // Eat identifier token. Operands.push_back(ARMOperand::CreateCoprocNum(Num, S)); @@ -3188,6 +3228,7 @@ ARMAsmParser::parseCoprocNumOperand(OperandVector &Operands) { /// number, the token is eaten and the operand is added to the operand list. ARMAsmParser::OperandMatchResultTy ARMAsmParser::parseCoprocRegOperand(OperandVector &Operands) { + MCAsmParser &Parser = getParser(); SMLoc S = Parser.getTok().getLoc(); const AsmToken &Tok = Parser.getTok(); if (Tok.isNot(AsmToken::Identifier)) @@ -3206,6 +3247,7 @@ ARMAsmParser::parseCoprocRegOperand(OperandVector &Operands) { /// coproc_option : '{' imm0_255 '}' ARMAsmParser::OperandMatchResultTy ARMAsmParser::parseCoprocOptionOperand(OperandVector &Operands) { + MCAsmParser &Parser = getParser(); SMLoc S = Parser.getTok().getLoc(); // If this isn't a '{', this isn't a coprocessor immediate operand. @@ -3283,6 +3325,7 @@ static unsigned getDRegFromQReg(unsigned QReg) { /// Parse a register list. bool ARMAsmParser::parseRegisterList(OperandVector &Operands) { + MCAsmParser &Parser = getParser(); assert(Parser.getTok().is(AsmToken::LCurly) && "Token is not a Left Curly Brace"); SMLoc S = Parser.getTok().getLoc(); @@ -3414,6 +3457,7 @@ bool ARMAsmParser::parseRegisterList(OperandVector &Operands) { // Helper function to parse the lane index for vector lists. ARMAsmParser::OperandMatchResultTy ARMAsmParser:: parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index, SMLoc &EndLoc) { + MCAsmParser &Parser = getParser(); Index = 0; // Always return a defined index value. if (Parser.getTok().is(AsmToken::LBrac)) { Parser.Lex(); // Eat the '['. @@ -3465,6 +3509,7 @@ parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index, SMLoc &EndLoc) { // parse a vector register list ARMAsmParser::OperandMatchResultTy ARMAsmParser::parseVectorList(OperandVector &Operands) { + MCAsmParser &Parser = getParser(); VectorLaneTy LaneKind; unsigned LaneIndex; SMLoc S = Parser.getTok().getLoc(); @@ -3716,6 +3761,7 @@ ARMAsmParser::parseVectorList(OperandVector &Operands) { /// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options. ARMAsmParser::OperandMatchResultTy ARMAsmParser::parseMemBarrierOptOperand(OperandVector &Operands) { + MCAsmParser &Parser = getParser(); SMLoc S = Parser.getTok().getLoc(); const AsmToken &Tok = Parser.getTok(); unsigned Opt; @@ -3787,6 +3833,7 @@ ARMAsmParser::parseMemBarrierOptOperand(OperandVector &Operands) { /// parseInstSyncBarrierOptOperand - Try to parse ISB inst sync barrier options. ARMAsmParser::OperandMatchResultTy ARMAsmParser::parseInstSyncBarrierOptOperand(OperandVector &Operands) { + MCAsmParser &Parser = getParser(); SMLoc S = Parser.getTok().getLoc(); const AsmToken &Tok = Parser.getTok(); unsigned Opt; @@ -3838,6 +3885,7 @@ ARMAsmParser::parseInstSyncBarrierOptOperand(OperandVector &Operands) { /// parseProcIFlagsOperand - Try to parse iflags from CPS instruction. ARMAsmParser::OperandMatchResultTy ARMAsmParser::parseProcIFlagsOperand(OperandVector &Operands) { + MCAsmParser &Parser = getParser(); SMLoc S = Parser.getTok().getLoc(); const AsmToken &Tok = Parser.getTok(); if (!Tok.is(AsmToken::Identifier)) @@ -3872,6 +3920,7 @@ ARMAsmParser::parseProcIFlagsOperand(OperandVector &Operands) { /// parseMSRMaskOperand - Try to parse mask flags from MSR instruction. ARMAsmParser::OperandMatchResultTy ARMAsmParser::parseMSRMaskOperand(OperandVector &Operands) { + MCAsmParser &Parser = getParser(); SMLoc S = Parser.getTok().getLoc(); const AsmToken &Tok = Parser.getTok(); if (!Tok.is(AsmToken::Identifier)) @@ -3892,9 +3941,6 @@ ARMAsmParser::parseMSRMaskOperand(OperandVector &Operands) { // should really only be allowed when writing a special register. Note // they get dropped in the MRS instruction reading a special register as // the SYSm field is only 8 bits. - // - // FIXME: the _g and _nzcvqg versions are only allowed if the processor - // includes the DSP extension but that is not checked. .Case("apsr", 0x800) .Case("apsr_nzcvq", 0x800) .Case("apsr_g", 0x400) @@ -3926,6 +3972,11 @@ ARMAsmParser::parseMSRMaskOperand(OperandVector &Operands) { if (FlagsVal == ~0U) return MatchOperand_NoMatch; + if (!hasThumb2DSP() && (FlagsVal & 0x400)) + // The _g and _nzcvqg versions are only valid if the DSP extension is + // available. + return MatchOperand_NoMatch; + if (!hasV7Ops() && FlagsVal >= 0x811 && FlagsVal <= 0x813) // basepri, basepri_max and faultmask only valid for V7m. return MatchOperand_NoMatch; @@ -3998,9 +4049,67 @@ ARMAsmParser::parseMSRMaskOperand(OperandVector &Operands) { return MatchOperand_Success; } +/// parseBankedRegOperand - Try to parse a banked register (e.g. "lr_irq") for +/// use in the MRS/MSR instructions added to support virtualization. +ARMAsmParser::OperandMatchResultTy +ARMAsmParser::parseBankedRegOperand(OperandVector &Operands) { + MCAsmParser &Parser = getParser(); + SMLoc S = Parser.getTok().getLoc(); + const AsmToken &Tok = Parser.getTok(); + if (!Tok.is(AsmToken::Identifier)) + return MatchOperand_NoMatch; + StringRef RegName = Tok.getString(); + + // The values here come from B9.2.3 of the ARM ARM, where bits 4-0 are SysM + // and bit 5 is R. + unsigned Encoding = StringSwitch(RegName.lower()) + .Case("r8_usr", 0x00) + .Case("r9_usr", 0x01) + .Case("r10_usr", 0x02) + .Case("r11_usr", 0x03) + .Case("r12_usr", 0x04) + .Case("sp_usr", 0x05) + .Case("lr_usr", 0x06) + .Case("r8_fiq", 0x08) + .Case("r9_fiq", 0x09) + .Case("r10_fiq", 0x0a) + .Case("r11_fiq", 0x0b) + .Case("r12_fiq", 0x0c) + .Case("sp_fiq", 0x0d) + .Case("lr_fiq", 0x0e) + .Case("lr_irq", 0x10) + .Case("sp_irq", 0x11) + .Case("lr_svc", 0x12) + .Case("sp_svc", 0x13) + .Case("lr_abt", 0x14) + .Case("sp_abt", 0x15) + .Case("lr_und", 0x16) + .Case("sp_und", 0x17) + .Case("lr_mon", 0x1c) + .Case("sp_mon", 0x1d) + .Case("elr_hyp", 0x1e) + .Case("sp_hyp", 0x1f) + .Case("spsr_fiq", 0x2e) + .Case("spsr_irq", 0x30) + .Case("spsr_svc", 0x32) + .Case("spsr_abt", 0x34) + .Case("spsr_und", 0x36) + .Case("spsr_mon", 0x3c) + .Case("spsr_hyp", 0x3e) + .Default(~0U); + + if (Encoding == ~0U) + return MatchOperand_NoMatch; + + Parser.Lex(); // Eat identifier token. + Operands.push_back(ARMOperand::CreateBankedReg(Encoding, S)); + return MatchOperand_Success; +} + ARMAsmParser::OperandMatchResultTy ARMAsmParser::parsePKHImm(OperandVector &Operands, StringRef Op, int Low, int High) { + MCAsmParser &Parser = getParser(); const AsmToken &Tok = Parser.getTok(); if (Tok.isNot(AsmToken::Identifier)) { Error(Parser.getTok().getLoc(), Op + " operand expected."); @@ -4048,6 +4157,7 @@ ARMAsmParser::parsePKHImm(OperandVector &Operands, StringRef Op, int Low, ARMAsmParser::OperandMatchResultTy ARMAsmParser::parseSetEndImm(OperandVector &Operands) { + MCAsmParser &Parser = getParser(); const AsmToken &Tok = Parser.getTok(); SMLoc S = Tok.getLoc(); if (Tok.isNot(AsmToken::Identifier)) { @@ -4064,7 +4174,7 @@ ARMAsmParser::parseSetEndImm(OperandVector &Operands) { Error(S, "'be' or 'le' operand expected"); return MatchOperand_ParseFail; } - Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val, + Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::create(Val, getContext()), S, Tok.getEndLoc())); return MatchOperand_Success; @@ -4077,6 +4187,7 @@ ARMAsmParser::parseSetEndImm(OperandVector &Operands) { /// n == 32 encoded as n == 0. ARMAsmParser::OperandMatchResultTy ARMAsmParser::parseShifterImm(OperandVector &Operands) { + MCAsmParser &Parser = getParser(); const AsmToken &Tok = Parser.getTok(); SMLoc S = Tok.getLoc(); if (Tok.isNot(AsmToken::Identifier)) { @@ -4147,6 +4258,7 @@ ARMAsmParser::parseShifterImm(OperandVector &Operands) { /// ror #n 'n' in {0, 8, 16, 24} ARMAsmParser::OperandMatchResultTy ARMAsmParser::parseRotImm(OperandVector &Operands) { + MCAsmParser &Parser = getParser(); const AsmToken &Tok = Parser.getTok(); SMLoc S = Tok.getLoc(); if (Tok.isNot(AsmToken::Identifier)) @@ -4191,8 +4303,126 @@ ARMAsmParser::parseRotImm(OperandVector &Operands) { return MatchOperand_Success; } +ARMAsmParser::OperandMatchResultTy +ARMAsmParser::parseModImm(OperandVector &Operands) { + MCAsmParser &Parser = getParser(); + MCAsmLexer &Lexer = getLexer(); + int64_t Imm1, Imm2; + + SMLoc S = Parser.getTok().getLoc(); + + // 1) A mod_imm operand can appear in the place of a register name: + // add r0, #mod_imm + // add r0, r0, #mod_imm + // to correctly handle the latter, we bail out as soon as we see an + // identifier. + // + // 2) Similarly, we do not want to parse into complex operands: + // mov r0, #mod_imm + // mov r0, :lower16:(_foo) + if (Parser.getTok().is(AsmToken::Identifier) || + Parser.getTok().is(AsmToken::Colon)) + return MatchOperand_NoMatch; + + // Hash (dollar) is optional as per the ARMARM + if (Parser.getTok().is(AsmToken::Hash) || + Parser.getTok().is(AsmToken::Dollar)) { + // Avoid parsing into complex operands (#:) + if (Lexer.peekTok().is(AsmToken::Colon)) + return MatchOperand_NoMatch; + + // Eat the hash (dollar) + Parser.Lex(); + } + + SMLoc Sx1, Ex1; + Sx1 = Parser.getTok().getLoc(); + const MCExpr *Imm1Exp; + if (getParser().parseExpression(Imm1Exp, Ex1)) { + Error(Sx1, "malformed expression"); + return MatchOperand_ParseFail; + } + + const MCConstantExpr *CE = dyn_cast(Imm1Exp); + + if (CE) { + // Immediate must fit within 32-bits + Imm1 = CE->getValue(); + int Enc = ARM_AM::getSOImmVal(Imm1); + if (Enc != -1 && Parser.getTok().is(AsmToken::EndOfStatement)) { + // We have a match! + Operands.push_back(ARMOperand::CreateModImm((Enc & 0xFF), + (Enc & 0xF00) >> 7, + Sx1, Ex1)); + return MatchOperand_Success; + } + + // We have parsed an immediate which is not for us, fallback to a plain + // immediate. This can happen for instruction aliases. For an example, + // ARMInstrInfo.td defines the alias [mov <-> mvn] which can transform + // a mov (mvn) with a mod_imm_neg/mod_imm_not operand into the opposite + // instruction with a mod_imm operand. The alias is defined such that the + // parser method is shared, that's why we have to do this here. + if (Parser.getTok().is(AsmToken::EndOfStatement)) { + Operands.push_back(ARMOperand::CreateImm(Imm1Exp, Sx1, Ex1)); + return MatchOperand_Success; + } + } else { + // Operands like #(l1 - l2) can only be evaluated at a later stage (via an + // MCFixup). Fallback to a plain immediate. + Operands.push_back(ARMOperand::CreateImm(Imm1Exp, Sx1, Ex1)); + return MatchOperand_Success; + } + + // From this point onward, we expect the input to be a (#bits, #rot) pair + if (Parser.getTok().isNot(AsmToken::Comma)) { + Error(Sx1, "expected modified immediate operand: #[0, 255], #even[0-30]"); + return MatchOperand_ParseFail; + } + + if (Imm1 & ~0xFF) { + Error(Sx1, "immediate operand must a number in the range [0, 255]"); + return MatchOperand_ParseFail; + } + + // Eat the comma + Parser.Lex(); + + // Repeat for #rot + SMLoc Sx2, Ex2; + Sx2 = Parser.getTok().getLoc(); + + // Eat the optional hash (dollar) + if (Parser.getTok().is(AsmToken::Hash) || + Parser.getTok().is(AsmToken::Dollar)) + Parser.Lex(); + + const MCExpr *Imm2Exp; + if (getParser().parseExpression(Imm2Exp, Ex2)) { + Error(Sx2, "malformed expression"); + return MatchOperand_ParseFail; + } + + CE = dyn_cast(Imm2Exp); + + if (CE) { + Imm2 = CE->getValue(); + if (!(Imm2 & ~0x1E)) { + // We have a match! + Operands.push_back(ARMOperand::CreateModImm(Imm1, Imm2, S, Ex2)); + return MatchOperand_Success; + } + Error(Sx2, "immediate operand must an even number in the range [0, 30]"); + return MatchOperand_ParseFail; + } else { + Error(Sx2, "constant expression expected"); + return MatchOperand_ParseFail; + } +} + ARMAsmParser::OperandMatchResultTy ARMAsmParser::parseBitfield(OperandVector &Operands) { + MCAsmParser &Parser = getParser(); SMLoc S = Parser.getTok().getLoc(); // The bitfield descriptor is really two operands, the LSB and the width. if (Parser.getTok().isNot(AsmToken::Hash) && @@ -4269,6 +4499,7 @@ ARMAsmParser::parsePostIdxReg(OperandVector &Operands) { // This method must return MatchOperand_NoMatch without consuming any tokens // in the case where there is no match, as other alternatives take other // parse methods. + MCAsmParser &Parser = getParser(); AsmToken Tok = Parser.getTok(); SMLoc S = Tok.getLoc(); bool haveEaten = false; @@ -4321,6 +4552,7 @@ ARMAsmParser::parseAM3Offset(OperandVector &Operands) { // This method must return MatchOperand_NoMatch without consuming any tokens // in the case where there is no match, as other alternatives take other // parse methods. + MCAsmParser &Parser = getParser(); AsmToken Tok = Parser.getTok(); SMLoc S = Tok.getLoc(); @@ -4346,7 +4578,7 @@ ARMAsmParser::parseAM3Offset(OperandVector &Operands) { Val = INT32_MIN; Operands.push_back( - ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E)); + ARMOperand::CreateImm(MCConstantExpr::create(Val, getContext()), S, E)); return MatchOperand_Success; } @@ -4458,6 +4690,7 @@ void ARMAsmParser::cvtThumbBranches(MCInst &Inst, /// Parse an ARM memory expression, return false if successful else return true /// or an error. The first token must be a '[' when called. bool ARMAsmParser::parseMemory(OperandVector &Operands) { + MCAsmParser &Parser = getParser(); SMLoc S, E; assert(Parser.getTok().is(AsmToken::LBrac) && "Token is not a Left Bracket"); @@ -4575,7 +4808,7 @@ bool ARMAsmParser::parseMemory(OperandVector &Operands) { // If the constant was #-0, represent it as INT32_MIN. int32_t Val = CE->getValue(); if (isNegative && Val == 0) - CE = MCConstantExpr::Create(INT32_MIN, getContext()); + CE = MCConstantExpr::create(INT32_MIN, getContext()); // Now we should have the closing ']' if (Parser.getTok().isNot(AsmToken::RBrac)) @@ -4649,6 +4882,7 @@ bool ARMAsmParser::parseMemory(OperandVector &Operands) { /// return true if it parses a shift otherwise it returns false. bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St, unsigned &Amount) { + MCAsmParser &Parser = getParser(); SMLoc Loc = Parser.getTok().getLoc(); const AsmToken &Tok = Parser.getTok(); if (Tok.isNot(AsmToken::Identifier)) @@ -4709,6 +4943,7 @@ bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St, /// parseFPImm - A floating point immediate expression operand. ARMAsmParser::OperandMatchResultTy ARMAsmParser::parseFPImm(OperandVector &Operands) { + MCAsmParser &Parser = getParser(); // Anything that can accept a floating point constant as an operand // needs to go through here, as the regular parseExpression is // integer only. @@ -4760,7 +4995,7 @@ ARMAsmParser::parseFPImm(OperandVector &Operands) { IntVal ^= (uint64_t)isNegative << 31; Parser.Lex(); // Eat the token. Operands.push_back(ARMOperand::CreateImm( - MCConstantExpr::Create(IntVal, getContext()), + MCConstantExpr::create(IntVal, getContext()), S, Parser.getTok().getLoc())); return MatchOperand_Success; } @@ -4777,7 +5012,7 @@ ARMAsmParser::parseFPImm(OperandVector &Operands) { Val = APFloat(RealVal).bitcastToAPInt().getZExtValue(); Operands.push_back(ARMOperand::CreateImm( - MCConstantExpr::Create(Val, getContext()), S, + MCConstantExpr::create(Val, getContext()), S, Parser.getTok().getLoc())); return MatchOperand_Success; } @@ -4789,6 +5024,7 @@ ARMAsmParser::parseFPImm(OperandVector &Operands) { /// Parse a arm instruction operand. For now this parses the operand regardless /// of the mnemonic. bool ARMAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) { + MCAsmParser &Parser = getParser(); SMLoc S, E; // Check if the current operand has a custom associated parser, if so, try to @@ -4865,7 +5101,7 @@ bool ARMAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) { if (CE) { int32_t Val = CE->getValue(); if (isNegative && Val == 0) - ImmVal = MCConstantExpr::Create(INT32_MIN, getContext()); + ImmVal = MCConstantExpr::create(INT32_MIN, getContext()); } E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E)); @@ -4895,7 +5131,7 @@ bool ARMAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) { if (getParser().parseExpression(SubExprVal)) return true; - const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal, + const MCExpr *ExprVal = ARMMCExpr::create(RefKind, SubExprVal, getContext()); E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E)); @@ -4921,6 +5157,7 @@ bool ARMAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) { // parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e. // :lower16: and :upper16:. bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) { + MCAsmParser &Parser = getParser(); RefKind = ARMMCExpr::VK_ARM_None; // consume an optional '#' (GNU compatibility) @@ -4936,15 +5173,52 @@ bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) { return true; } + enum { + COFF = (1 << MCObjectFileInfo::IsCOFF), + ELF = (1 << MCObjectFileInfo::IsELF), + MACHO = (1 << MCObjectFileInfo::IsMachO) + }; + static const struct PrefixEntry { + const char *Spelling; + ARMMCExpr::VariantKind VariantKind; + uint8_t SupportedFormats; + } PrefixEntries[] = { + { "lower16", ARMMCExpr::VK_ARM_LO16, COFF | ELF | MACHO }, + { "upper16", ARMMCExpr::VK_ARM_HI16, COFF | ELF | MACHO }, + }; + StringRef IDVal = Parser.getTok().getIdentifier(); - if (IDVal == "lower16") { - RefKind = ARMMCExpr::VK_ARM_LO16; - } else if (IDVal == "upper16") { - RefKind = ARMMCExpr::VK_ARM_HI16; - } else { + + const auto &Prefix = + std::find_if(std::begin(PrefixEntries), std::end(PrefixEntries), + [&IDVal](const PrefixEntry &PE) { + return PE.Spelling == IDVal; + }); + if (Prefix == std::end(PrefixEntries)) { Error(Parser.getTok().getLoc(), "unexpected prefix in operand"); return true; } + + uint8_t CurrentFormat; + switch (getContext().getObjectFileInfo()->getObjectFileType()) { + case MCObjectFileInfo::IsMachO: + CurrentFormat = MACHO; + break; + case MCObjectFileInfo::IsELF: + CurrentFormat = ELF; + break; + case MCObjectFileInfo::IsCOFF: + CurrentFormat = COFF; + break; + } + + if (~Prefix->SupportedFormats & CurrentFormat) { + Error(Parser.getTok().getLoc(), + "cannot represent relocation in the current file format"); + return true; + } + + RefKind = Prefix->VariantKind; Parser.Lex(); if (getLexer().isNot(AsmToken::Colon)) { @@ -4952,6 +5226,7 @@ bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) { return true; } Parser.Lex(); // Eat the last ':' + return false; } @@ -4984,7 +5259,8 @@ StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic, Mnemonic == "fmuls" || Mnemonic == "vmaxnm" || Mnemonic == "vminnm" || Mnemonic == "vcvta" || Mnemonic == "vcvtn" || Mnemonic == "vcvtp" || Mnemonic == "vcvtm" || Mnemonic == "vrinta" || Mnemonic == "vrintn" || - Mnemonic == "vrintp" || Mnemonic == "vrintm" || Mnemonic.startswith("vsel")) + Mnemonic == "vrintp" || Mnemonic == "vrintm" || Mnemonic == "hvc" || + Mnemonic.startswith("vsel")) return Mnemonic; // First, split out any predication code. Ignore mnemonics we know aren't @@ -5063,47 +5339,44 @@ StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic, /// inclusion of carry set or predication code operands. // // FIXME: It would be nice to autogen this. -void ARMAsmParser:: -getMnemonicAcceptInfo(StringRef Mnemonic, StringRef FullInst, - bool &CanAcceptCarrySet, bool &CanAcceptPredicationCode) { - if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" || +void ARMAsmParser::getMnemonicAcceptInfo(StringRef Mnemonic, StringRef FullInst, + bool &CanAcceptCarrySet, + bool &CanAcceptPredicationCode) { + CanAcceptCarrySet = + Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" || Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" || - Mnemonic == "add" || Mnemonic == "adc" || - Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" || - Mnemonic == "orr" || Mnemonic == "mvn" || - Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" || - Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" || - Mnemonic == "vfm" || Mnemonic == "vfnm" || - (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" || - Mnemonic == "mla" || Mnemonic == "smlal" || - Mnemonic == "umlal" || Mnemonic == "umull"))) { - CanAcceptCarrySet = true; - } else - CanAcceptCarrySet = false; + Mnemonic == "add" || Mnemonic == "adc" || Mnemonic == "mul" || + Mnemonic == "bic" || Mnemonic == "asr" || Mnemonic == "orr" || + Mnemonic == "mvn" || Mnemonic == "rsb" || Mnemonic == "rsc" || + Mnemonic == "orn" || Mnemonic == "sbc" || Mnemonic == "eor" || + Mnemonic == "neg" || Mnemonic == "vfm" || Mnemonic == "vfnm" || + (!isThumb() && + (Mnemonic == "smull" || Mnemonic == "mov" || Mnemonic == "mla" || + Mnemonic == "smlal" || Mnemonic == "umlal" || Mnemonic == "umull")); if (Mnemonic == "bkpt" || Mnemonic == "cbnz" || Mnemonic == "setend" || - Mnemonic == "cps" || Mnemonic == "it" || Mnemonic == "cbz" || + Mnemonic == "cps" || Mnemonic == "it" || Mnemonic == "cbz" || Mnemonic == "trap" || Mnemonic == "hlt" || Mnemonic == "udf" || Mnemonic.startswith("crc32") || Mnemonic.startswith("cps") || - Mnemonic.startswith("vsel") || - Mnemonic == "vmaxnm" || Mnemonic == "vminnm" || Mnemonic == "vcvta" || - Mnemonic == "vcvtn" || Mnemonic == "vcvtp" || Mnemonic == "vcvtm" || - Mnemonic == "vrinta" || Mnemonic == "vrintn" || Mnemonic == "vrintp" || - Mnemonic == "vrintm" || Mnemonic.startswith("aes") || + Mnemonic.startswith("vsel") || Mnemonic == "vmaxnm" || + Mnemonic == "vminnm" || Mnemonic == "vcvta" || Mnemonic == "vcvtn" || + Mnemonic == "vcvtp" || Mnemonic == "vcvtm" || Mnemonic == "vrinta" || + Mnemonic == "vrintn" || Mnemonic == "vrintp" || Mnemonic == "vrintm" || + Mnemonic.startswith("aes") || Mnemonic == "hvc" || Mnemonic == "setpan" || Mnemonic.startswith("sha1") || Mnemonic.startswith("sha256") || (FullInst.startswith("vmull") && FullInst.endswith(".p64"))) { // These mnemonics are never predicable CanAcceptPredicationCode = false; } else if (!isThumb()) { // Some instructions are only predicable in Thumb mode - CanAcceptPredicationCode - = Mnemonic != "cdp2" && Mnemonic != "clrex" && Mnemonic != "mcr2" && + CanAcceptPredicationCode = + Mnemonic != "cdp2" && Mnemonic != "clrex" && Mnemonic != "mcr2" && Mnemonic != "mcrr2" && Mnemonic != "mrc2" && Mnemonic != "mrrc2" && Mnemonic != "dmb" && Mnemonic != "dsb" && Mnemonic != "isb" && Mnemonic != "pld" && Mnemonic != "pli" && Mnemonic != "pldw" && - Mnemonic != "ldc2" && Mnemonic != "ldc2l" && - Mnemonic != "stc2" && Mnemonic != "stc2l" && - !Mnemonic.startswith("rfe") && !Mnemonic.startswith("srs"); + Mnemonic != "ldc2" && Mnemonic != "ldc2l" && Mnemonic != "stc2" && + Mnemonic != "stc2l" && !Mnemonic.startswith("rfe") && + !Mnemonic.startswith("srs"); } else if (isThumbOne()) { if (hasV6MOps()) CanAcceptPredicationCode = Mnemonic != "movs"; @@ -5113,6 +5386,92 @@ getMnemonicAcceptInfo(StringRef Mnemonic, StringRef FullInst, CanAcceptPredicationCode = true; } +// \brief Some Thumb instructions have two operand forms that are not +// available as three operand, convert to two operand form if possible. +// +// FIXME: We would really like to be able to tablegen'erate this. +void ARMAsmParser::tryConvertingToTwoOperandForm(StringRef Mnemonic, + bool CarrySetting, + OperandVector &Operands) { + if (Operands.size() != 6) + return; + + const auto &Op3 = static_cast(*Operands[3]); + auto &Op4 = static_cast(*Operands[4]); + if (!Op3.isReg() || !Op4.isReg()) + return; + + auto Op3Reg = Op3.getReg(); + auto Op4Reg = Op4.getReg(); + + // For most Thumb2 cases we just generate the 3 operand form and reduce + // it in processInstruction(), but the 3 operand form of ADD (t2ADDrr) + // won't accept SP or PC so we do the transformation here taking care + // with immediate range in the 'add sp, sp #imm' case. + auto &Op5 = static_cast(*Operands[5]); + if (isThumbTwo()) { + if (Mnemonic != "add") + return; + bool TryTransform = Op3Reg == ARM::PC || Op4Reg == ARM::PC || + (Op5.isReg() && Op5.getReg() == ARM::PC); + if (!TryTransform) { + TryTransform = (Op3Reg == ARM::SP || Op4Reg == ARM::SP || + (Op5.isReg() && Op5.getReg() == ARM::SP)) && + !(Op3Reg == ARM::SP && Op4Reg == ARM::SP && + Op5.isImm() && !Op5.isImm0_508s4()); + } + if (!TryTransform) + return; + } else if (!isThumbOne()) + return; + + if (!(Mnemonic == "add" || Mnemonic == "sub" || Mnemonic == "and" || + Mnemonic == "eor" || Mnemonic == "lsl" || Mnemonic == "lsr" || + Mnemonic == "asr" || Mnemonic == "adc" || Mnemonic == "sbc" || + Mnemonic == "ror" || Mnemonic == "orr" || Mnemonic == "bic")) + return; + + // If first 2 operands of a 3 operand instruction are the same + // then transform to 2 operand version of the same instruction + // e.g. 'adds r0, r0, #1' transforms to 'adds r0, #1' + bool Transform = Op3Reg == Op4Reg; + + // For communtative operations, we might be able to transform if we swap + // Op4 and Op5. The 'ADD Rdm, SP, Rdm' form is already handled specially + // as tADDrsp. + const ARMOperand *LastOp = &Op5; + bool Swap = false; + if (!Transform && Op5.isReg() && Op3Reg == Op5.getReg() && + ((Mnemonic == "add" && Op4Reg != ARM::SP) || + Mnemonic == "and" || Mnemonic == "eor" || + Mnemonic == "adc" || Mnemonic == "orr")) { + Swap = true; + LastOp = &Op4; + Transform = true; + } + + // If both registers are the same then remove one of them from + // the operand list, with certain exceptions. + if (Transform) { + // Don't transform 'adds Rd, Rd, Rm' or 'sub{s} Rd, Rd, Rm' because the + // 2 operand forms don't exist. + if (((Mnemonic == "add" && CarrySetting) || Mnemonic == "sub") && + LastOp->isReg()) + Transform = false; + + // Don't transform 'add/sub{s} Rd, Rd, #imm' if the immediate fits into + // 3-bits because the ARMARM says not to. + if ((Mnemonic == "add" || Mnemonic == "sub") && LastOp->isImm0_7()) + Transform = false; + } + + if (Transform) { + if (Swap) + std::swap(Op4, Op5); + Operands.erase(Operands.begin() + 3); + } +} + bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic, OperandVector &Operands) { // FIXME: This is all horribly hacky. We really need a better way to deal @@ -5127,7 +5486,7 @@ bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic, // conditionally adding the cc_out in the first place because we need // to check the type of the parsed immediate operand. if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() && - !static_cast(*Operands[4]).isARMSOImm() && + !static_cast(*Operands[4]).isModImm() && static_cast(*Operands[4]).isImm0_65535Expr() && static_cast(*Operands[1]).getReg() == 0) return true; @@ -5271,7 +5630,7 @@ static bool isDataTypeToken(StringRef Tok) { static bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) { return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm"); } -static void applyMnemonicAliases(StringRef &Mnemonic, unsigned Features, +static void applyMnemonicAliases(StringRef &Mnemonic, uint64_t Features, unsigned VariantID); static bool RequiresVFPRegListValidation(StringRef Inst, @@ -5296,6 +5655,7 @@ static bool RequiresVFPRegListValidation(StringRef Inst, /// Parse an arm instruction mnemonic followed by its operands. bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, OperandVector &Operands) { + MCAsmParser &Parser = getParser(); // FIXME: Can this be done via tablegen in some fashion? bool RequireVFPRegisterListCheck; bool AcceptSinglePrecisionOnly; @@ -5309,7 +5669,7 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, // The generic tblgen'erated code does this later, at the start of // MatchInstructionImpl(), but that's too late for aliases that include // any sort of suffix. - unsigned AvailableFeatures = getAvailableFeatures(); + uint64_t AvailableFeatures = getAvailableFeatures(); unsigned AssemblerDialect = getParser().getAssemblerDialect(); applyMnemonicAliases(Name, AvailableFeatures, AssemblerDialect); @@ -5413,8 +5773,10 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, // Add the processor imod operand, if necessary. if (ProcessorIMod) { Operands.push_back(ARMOperand::CreateImm( - MCConstantExpr::Create(ProcessorIMod, getContext()), + MCConstantExpr::create(ProcessorIMod, getContext()), NameLoc, NameLoc)); + } else if (Mnemonic == "cps" && isMClass()) { + return Error(NameLoc, "instruction 'cps' requires effect for M-class"); } // Add the remaining tokens in the mnemonic. @@ -5483,11 +5845,13 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, "VFP/Neon double precision register expected"); } + tryConvertingToTwoOperandForm(Mnemonic, CarrySetting, Operands); + // Some instructions, mostly Thumb, have forms for the same mnemonic that // do and don't have a cc_out optional-def operand. With some spot-checks // of the operand list, we can figure out which variant we're trying to // parse and adjust accordingly before actually matching. We shouldn't ever - // try to remove a cc_out operand that was explicitly set on the the + // try to remove a cc_out operand that was explicitly set on the // mnemonic, of course (CarrySetting == true). Reason number #317 the // table driven matcher doesn't fit well with the ARM instruction set. if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) @@ -5588,8 +5952,9 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, // return 'true' if register list contains non-low GPR registers, // 'false' otherwise. If Reg is in the register list or is HiReg, set // 'containsReg' to true. -static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg, - unsigned HiReg, bool &containsReg) { +static bool checkLowRegisterList(const MCInst &Inst, unsigned OpNo, + unsigned Reg, unsigned HiReg, + bool &containsReg) { containsReg = false; for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) { unsigned OpReg = Inst.getOperand(i).getReg(); @@ -5604,8 +5969,8 @@ static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg, // Check if the specified regisgter is in the register list of the inst, // starting at the indicated operand number. -static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) { - for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) { +static bool listContainsReg(const MCInst &Inst, unsigned OpNo, unsigned Reg) { + for (unsigned i = OpNo, e = Inst.getNumOperands(); i < e; ++i) { unsigned OpReg = Inst.getOperand(i).getReg(); if (OpReg == Reg) return true; @@ -5623,6 +5988,50 @@ static bool instIsBreakpoint(const MCInst &Inst) { } +bool ARMAsmParser::validatetLDMRegList(const MCInst &Inst, + const OperandVector &Operands, + unsigned ListNo, bool IsARPop) { + const ARMOperand &Op = static_cast(*Operands[ListNo]); + bool HasWritebackToken = Op.isToken() && Op.getToken() == "!"; + + bool ListContainsSP = listContainsReg(Inst, ListNo, ARM::SP); + bool ListContainsLR = listContainsReg(Inst, ListNo, ARM::LR); + bool ListContainsPC = listContainsReg(Inst, ListNo, ARM::PC); + + if (!IsARPop && ListContainsSP) + return Error(Operands[ListNo + HasWritebackToken]->getStartLoc(), + "SP may not be in the register list"); + else if (ListContainsPC && ListContainsLR) + return Error(Operands[ListNo + HasWritebackToken]->getStartLoc(), + "PC and LR may not be in the register list simultaneously"); + else if (inITBlock() && !lastInITBlock() && ListContainsPC) + return Error(Operands[ListNo + HasWritebackToken]->getStartLoc(), + "instruction must be outside of IT block or the last " + "instruction in an IT block"); + return false; +} + +bool ARMAsmParser::validatetSTMRegList(const MCInst &Inst, + const OperandVector &Operands, + unsigned ListNo) { + const ARMOperand &Op = static_cast(*Operands[ListNo]); + bool HasWritebackToken = Op.isToken() && Op.getToken() == "!"; + + bool ListContainsSP = listContainsReg(Inst, ListNo, ARM::SP); + bool ListContainsPC = listContainsReg(Inst, ListNo, ARM::PC); + + if (ListContainsSP && ListContainsPC) + return Error(Operands[ListNo + HasWritebackToken]->getStartLoc(), + "SP and PC may not be in the register list"); + else if (ListContainsSP) + return Error(Operands[ListNo + HasWritebackToken]->getStartLoc(), + "SP may not be in the register list"); + else if (ListContainsPC) + return Error(Operands[ListNo + HasWritebackToken]->getStartLoc(), + "PC may not be in the register list"); + return false; +} + // FIXME: We would really like to be able to tablegen'erate this. bool ARMAsmParser::validateInstruction(MCInst &Inst, const OperandVector &Operands) { @@ -5709,6 +6118,14 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, "destination operands can't be identical"); return false; } + case ARM::t2BXJ: { + const unsigned RmReg = Inst.getOperand(0).getReg(); + // Rm = SP is no longer unpredictable in v8-A + if (RmReg == ARM::SP && !hasV8Ops()) + return Error(Operands[2]->getStartLoc(), + "r13 (SP) is an unpredictable operand to BXJ"); + return false; + } case ARM::STRD: { // Rt2 must be Rt + 1. unsigned Rt = MRI->getEncodingValue(Inst.getOperand(0).getReg()); @@ -5754,7 +6171,13 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, case ARM::LDRH_PRE: case ARM::LDRH_POST: case ARM::LDRSH_PRE: - case ARM::LDRSH_POST: { + case ARM::LDRSH_POST: + case ARM::LDRB_PRE_IMM: + case ARM::LDRB_PRE_REG: + case ARM::LDRB_POST_IMM: + case ARM::LDRB_POST_REG: + case ARM::LDRSB_PRE: + case ARM::LDRSB_POST: { // Rt must be different from Rn. const unsigned Rt = MRI->getEncodingValue(Inst.getOperand(0).getReg()); const unsigned Rn = MRI->getEncodingValue(Inst.getOperand(2).getReg()); @@ -5801,6 +6224,8 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, "writeback operator '!' not allowed when base register " "in register list"); + if (validatetLDMRegList(Inst, Operands, 3)) + return true; break; } case ARM::LDMIA_UPD: @@ -5811,7 +6236,20 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, // UNPREDICTABLE on v7 upwards. Goodness knows what they did before. if (!hasV7Ops()) break; - // Fallthrough + if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg())) + return Error(Operands.back()->getStartLoc(), + "writeback register not allowed in register list"); + break; + case ARM::t2LDMIA: + case ARM::t2LDMDB: + if (validatetLDMRegList(Inst, Operands, 3)) + return true; + break; + case ARM::t2STMIA: + case ARM::t2STMDB: + if (validatetSTMRegList(Inst, Operands, 3)) + return true; + break; case ARM::t2LDMIA_UPD: case ARM::t2LDMDB_UPD: case ARM::t2STMIA_UPD: @@ -5819,6 +6257,14 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg())) return Error(Operands.back()->getStartLoc(), "writeback register not allowed in register list"); + + if (Opcode == ARM::t2LDMIA_UPD || Opcode == ARM::t2LDMDB_UPD) { + if (validatetLDMRegList(Inst, Operands, 3)) + return true; + } else { + if (validatetSTMRegList(Inst, Operands, 3)) + return true; + } break; } case ARM::sysLDMIA_UPD: @@ -5863,6 +6309,8 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, !isThumbTwo()) return Error(Operands[2]->getStartLoc(), "registers must be in range r0-r7 or pc"); + if (validatetLDMRegList(Inst, Operands, 2, !isMClass())) + return true; break; } case ARM::tPUSH: { @@ -5871,6 +6319,8 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, !isThumbTwo()) return Error(Operands[2]->getStartLoc(), "registers must be in range r0-r7 or lr"); + if (validatetSTMRegList(Inst, Operands, 2)) + return true; break; } case ARM::tSTMIA_UPD: { @@ -5887,6 +6337,9 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, return Error(Operands[4]->getStartLoc(), "writeback operator '!' not allowed when base register " "in register list"); + + if (validatetSTMRegList(Inst, Operands, 4)) + return true; break; } case ARM::tADDrSP: { @@ -6207,7 +6660,8 @@ static unsigned getRealVLDOpcode(unsigned Opc, unsigned &Spacing) { } bool ARMAsmParser::processInstruction(MCInst &Inst, - const OperandVector &Operands) { + const OperandVector &Operands, + MCStreamer &Out) { switch (Inst.getOpcode()) { // Alias for alternate form of 'ldr{,b}t Rt, [Rn], #imm' instruction. case ARM::LDRT_POST: @@ -6220,8 +6674,8 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, TmpInst.addOperand(Inst.getOperand(0)); TmpInst.addOperand(Inst.getOperand(1)); TmpInst.addOperand(Inst.getOperand(1)); - TmpInst.addOperand(MCOperand::CreateReg(0)); - TmpInst.addOperand(MCOperand::CreateImm(0)); + TmpInst.addOperand(MCOperand::createReg(0)); + TmpInst.addOperand(MCOperand::createImm(0)); TmpInst.addOperand(Inst.getOperand(2)); TmpInst.addOperand(Inst.getOperand(3)); Inst = TmpInst; @@ -6238,8 +6692,8 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, TmpInst.addOperand(Inst.getOperand(1)); TmpInst.addOperand(Inst.getOperand(0)); TmpInst.addOperand(Inst.getOperand(1)); - TmpInst.addOperand(MCOperand::CreateReg(0)); - TmpInst.addOperand(MCOperand::CreateImm(0)); + TmpInst.addOperand(MCOperand::createReg(0)); + TmpInst.addOperand(MCOperand::createImm(0)); TmpInst.addOperand(Inst.getOperand(2)); TmpInst.addOperand(Inst.getOperand(3)); Inst = TmpInst; @@ -6248,12 +6702,35 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, // Alias for alternate form of 'ADR Rd, #imm' instruction. case ARM::ADDri: { if (Inst.getOperand(1).getReg() != ARM::PC || - Inst.getOperand(5).getReg() != 0) + Inst.getOperand(5).getReg() != 0 || + !(Inst.getOperand(2).isExpr() || Inst.getOperand(2).isImm())) return false; MCInst TmpInst; TmpInst.setOpcode(ARM::ADR); TmpInst.addOperand(Inst.getOperand(0)); - TmpInst.addOperand(Inst.getOperand(2)); + if (Inst.getOperand(2).isImm()) { + // Immediate (mod_imm) will be in its encoded form, we must unencode it + // before passing it to the ADR instruction. + unsigned Enc = Inst.getOperand(2).getImm(); + TmpInst.addOperand(MCOperand::createImm( + ARM_AM::rotr32(Enc & 0xFF, (Enc & 0xF00) >> 7))); + } else { + // Turn PC-relative expression into absolute expression. + // Reading PC provides the start of the current instruction + 8 and + // the transform to adr is biased by that. + MCSymbol *Dot = getContext().createTempSymbol(); + Out.EmitLabel(Dot); + const MCExpr *OpExpr = Inst.getOperand(2).getExpr(); + const MCExpr *InstPC = MCSymbolRefExpr::create(Dot, + MCSymbolRefExpr::VK_None, + getContext()); + const MCExpr *Const8 = MCConstantExpr::create(8, getContext()); + const MCExpr *ReadPC = MCBinaryExpr::createAdd(InstPC, Const8, + getContext()); + const MCExpr *FixupAddr = MCBinaryExpr::createAdd(ReadPC, OpExpr, + getContext()); + TmpInst.addOperand(MCOperand::createExpr(FixupAddr)); + } TmpInst.addOperand(Inst.getOperand(3)); TmpInst.addOperand(Inst.getOperand(4)); Inst = TmpInst; @@ -6318,7 +6795,7 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, TmpInst.addOperand(Inst.getOperand(3)); // alignment TmpInst.addOperand(Inst.getOperand(4)); // Rm TmpInst.addOperand(Inst.getOperand(0)); // Vd - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing)); TmpInst.addOperand(Inst.getOperand(1)); // lane TmpInst.addOperand(Inst.getOperand(5)); // CondCode @@ -6342,9 +6819,9 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, TmpInst.addOperand(Inst.getOperand(3)); // alignment TmpInst.addOperand(Inst.getOperand(4)); // Rm TmpInst.addOperand(Inst.getOperand(0)); // Vd - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing)); - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing * 2)); TmpInst.addOperand(Inst.getOperand(1)); // lane TmpInst.addOperand(Inst.getOperand(5)); // CondCode @@ -6368,11 +6845,11 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, TmpInst.addOperand(Inst.getOperand(3)); // alignment TmpInst.addOperand(Inst.getOperand(4)); // Rm TmpInst.addOperand(Inst.getOperand(0)); // Vd - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing)); - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing * 2)); - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing * 3)); TmpInst.addOperand(Inst.getOperand(1)); // lane TmpInst.addOperand(Inst.getOperand(5)); // CondCode @@ -6392,7 +6869,7 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb TmpInst.addOperand(Inst.getOperand(2)); // Rn TmpInst.addOperand(Inst.getOperand(3)); // alignment - TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm + TmpInst.addOperand(MCOperand::createReg(0)); // Rm TmpInst.addOperand(Inst.getOperand(0)); // Vd TmpInst.addOperand(Inst.getOperand(1)); // lane TmpInst.addOperand(Inst.getOperand(4)); // CondCode @@ -6414,9 +6891,9 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb TmpInst.addOperand(Inst.getOperand(2)); // Rn TmpInst.addOperand(Inst.getOperand(3)); // alignment - TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm + TmpInst.addOperand(MCOperand::createReg(0)); // Rm TmpInst.addOperand(Inst.getOperand(0)); // Vd - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing)); TmpInst.addOperand(Inst.getOperand(1)); // lane TmpInst.addOperand(Inst.getOperand(4)); // CondCode @@ -6438,11 +6915,11 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb TmpInst.addOperand(Inst.getOperand(2)); // Rn TmpInst.addOperand(Inst.getOperand(3)); // alignment - TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm + TmpInst.addOperand(MCOperand::createReg(0)); // Rm TmpInst.addOperand(Inst.getOperand(0)); // Vd - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing)); - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing * 2)); TmpInst.addOperand(Inst.getOperand(1)); // lane TmpInst.addOperand(Inst.getOperand(4)); // CondCode @@ -6464,13 +6941,13 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb TmpInst.addOperand(Inst.getOperand(2)); // Rn TmpInst.addOperand(Inst.getOperand(3)); // alignment - TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm + TmpInst.addOperand(MCOperand::createReg(0)); // Rm TmpInst.addOperand(Inst.getOperand(0)); // Vd - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing)); - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing * 2)); - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing * 3)); TmpInst.addOperand(Inst.getOperand(1)); // lane TmpInst.addOperand(Inst.getOperand(4)); // CondCode @@ -6510,7 +6987,7 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, TmpInst.addOperand(Inst.getOperand(2)); // Rn TmpInst.addOperand(Inst.getOperand(3)); // alignment TmpInst.addOperand(Inst.getOperand(0)); // Vd - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing)); TmpInst.addOperand(Inst.getOperand(1)); // lane TmpInst.addOperand(Inst.getOperand(4)); // CondCode @@ -6532,9 +7009,9 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, TmpInst.addOperand(Inst.getOperand(2)); // Rn TmpInst.addOperand(Inst.getOperand(3)); // alignment TmpInst.addOperand(Inst.getOperand(0)); // Vd - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing)); - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing * 2)); TmpInst.addOperand(Inst.getOperand(1)); // lane TmpInst.addOperand(Inst.getOperand(4)); // CondCode @@ -6556,11 +7033,11 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, TmpInst.addOperand(Inst.getOperand(2)); // Rn TmpInst.addOperand(Inst.getOperand(3)); // alignment TmpInst.addOperand(Inst.getOperand(0)); // Vd - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing)); - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing * 2)); - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing * 3)); TmpInst.addOperand(Inst.getOperand(1)); // lane TmpInst.addOperand(Inst.getOperand(4)); // CondCode @@ -6602,14 +7079,14 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, unsigned Spacing; TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); TmpInst.addOperand(Inst.getOperand(0)); // Vd - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing)); TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb TmpInst.addOperand(Inst.getOperand(2)); // Rn TmpInst.addOperand(Inst.getOperand(3)); // alignment TmpInst.addOperand(Inst.getOperand(4)); // Rm TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd) - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing)); TmpInst.addOperand(Inst.getOperand(1)); // lane TmpInst.addOperand(Inst.getOperand(5)); // CondCode @@ -6629,18 +7106,18 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, unsigned Spacing; TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); TmpInst.addOperand(Inst.getOperand(0)); // Vd - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing)); - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing * 2)); TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb TmpInst.addOperand(Inst.getOperand(2)); // Rn TmpInst.addOperand(Inst.getOperand(3)); // alignment TmpInst.addOperand(Inst.getOperand(4)); // Rm TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd) - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing)); - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing * 2)); TmpInst.addOperand(Inst.getOperand(1)); // lane TmpInst.addOperand(Inst.getOperand(5)); // CondCode @@ -6660,22 +7137,22 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, unsigned Spacing; TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); TmpInst.addOperand(Inst.getOperand(0)); // Vd - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing)); - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing * 2)); - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing * 3)); TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb TmpInst.addOperand(Inst.getOperand(2)); // Rn TmpInst.addOperand(Inst.getOperand(3)); // alignment TmpInst.addOperand(Inst.getOperand(4)); // Rm TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd) - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing)); - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing * 2)); - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing * 3)); TmpInst.addOperand(Inst.getOperand(1)); // lane TmpInst.addOperand(Inst.getOperand(5)); // CondCode @@ -6696,7 +7173,7 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb TmpInst.addOperand(Inst.getOperand(2)); // Rn TmpInst.addOperand(Inst.getOperand(3)); // alignment - TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm + TmpInst.addOperand(MCOperand::createReg(0)); // Rm TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd) TmpInst.addOperand(Inst.getOperand(1)); // lane TmpInst.addOperand(Inst.getOperand(4)); // CondCode @@ -6716,14 +7193,14 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, unsigned Spacing; TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); TmpInst.addOperand(Inst.getOperand(0)); // Vd - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing)); TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb TmpInst.addOperand(Inst.getOperand(2)); // Rn TmpInst.addOperand(Inst.getOperand(3)); // alignment - TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm + TmpInst.addOperand(MCOperand::createReg(0)); // Rm TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd) - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing)); TmpInst.addOperand(Inst.getOperand(1)); // lane TmpInst.addOperand(Inst.getOperand(4)); // CondCode @@ -6743,18 +7220,18 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, unsigned Spacing; TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); TmpInst.addOperand(Inst.getOperand(0)); // Vd - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing)); - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing * 2)); TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb TmpInst.addOperand(Inst.getOperand(2)); // Rn TmpInst.addOperand(Inst.getOperand(3)); // alignment - TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm + TmpInst.addOperand(MCOperand::createReg(0)); // Rm TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd) - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing)); - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing * 2)); TmpInst.addOperand(Inst.getOperand(1)); // lane TmpInst.addOperand(Inst.getOperand(4)); // CondCode @@ -6774,22 +7251,22 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, unsigned Spacing; TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); TmpInst.addOperand(Inst.getOperand(0)); // Vd - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing)); - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing * 2)); - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing * 3)); TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb TmpInst.addOperand(Inst.getOperand(2)); // Rn TmpInst.addOperand(Inst.getOperand(3)); // alignment - TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm + TmpInst.addOperand(MCOperand::createReg(0)); // Rm TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd) - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing)); - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing * 2)); - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing * 3)); TmpInst.addOperand(Inst.getOperand(1)); // lane TmpInst.addOperand(Inst.getOperand(4)); // CondCode @@ -6828,12 +7305,12 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, unsigned Spacing; TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); TmpInst.addOperand(Inst.getOperand(0)); // Vd - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing)); TmpInst.addOperand(Inst.getOperand(2)); // Rn TmpInst.addOperand(Inst.getOperand(3)); // alignment TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd) - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing)); TmpInst.addOperand(Inst.getOperand(1)); // lane TmpInst.addOperand(Inst.getOperand(4)); // CondCode @@ -6853,16 +7330,16 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, unsigned Spacing; TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); TmpInst.addOperand(Inst.getOperand(0)); // Vd - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing)); - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing * 2)); TmpInst.addOperand(Inst.getOperand(2)); // Rn TmpInst.addOperand(Inst.getOperand(3)); // alignment TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd) - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing)); - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing * 2)); TmpInst.addOperand(Inst.getOperand(1)); // lane TmpInst.addOperand(Inst.getOperand(4)); // CondCode @@ -6882,20 +7359,20 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, unsigned Spacing; TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); TmpInst.addOperand(Inst.getOperand(0)); // Vd - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing)); - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing * 2)); - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing * 3)); TmpInst.addOperand(Inst.getOperand(2)); // Rn TmpInst.addOperand(Inst.getOperand(3)); // alignment TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd) - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing)); - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing * 2)); - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing * 3)); TmpInst.addOperand(Inst.getOperand(1)); // lane TmpInst.addOperand(Inst.getOperand(4)); // CondCode @@ -6915,9 +7392,9 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, unsigned Spacing; TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); TmpInst.addOperand(Inst.getOperand(0)); // Vd - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing)); - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing * 2)); TmpInst.addOperand(Inst.getOperand(1)); // Rn TmpInst.addOperand(Inst.getOperand(2)); // alignment @@ -6937,14 +7414,14 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, unsigned Spacing; TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); TmpInst.addOperand(Inst.getOperand(0)); // Vd - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing)); - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing * 2)); TmpInst.addOperand(Inst.getOperand(1)); // Rn TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn TmpInst.addOperand(Inst.getOperand(2)); // alignment - TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm + TmpInst.addOperand(MCOperand::createReg(0)); // Rm TmpInst.addOperand(Inst.getOperand(3)); // CondCode TmpInst.addOperand(Inst.getOperand(4)); Inst = TmpInst; @@ -6961,9 +7438,9 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, unsigned Spacing; TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); TmpInst.addOperand(Inst.getOperand(0)); // Vd - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing)); - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing * 2)); TmpInst.addOperand(Inst.getOperand(1)); // Rn TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn @@ -6986,9 +7463,9 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, unsigned Spacing; TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); TmpInst.addOperand(Inst.getOperand(0)); // Vd - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing)); - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing * 2)); TmpInst.addOperand(Inst.getOperand(1)); // Rn TmpInst.addOperand(Inst.getOperand(2)); // alignment @@ -7008,14 +7485,14 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, unsigned Spacing; TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); TmpInst.addOperand(Inst.getOperand(0)); // Vd - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing)); - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing * 2)); TmpInst.addOperand(Inst.getOperand(1)); // Rn TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn TmpInst.addOperand(Inst.getOperand(2)); // alignment - TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm + TmpInst.addOperand(MCOperand::createReg(0)); // Rm TmpInst.addOperand(Inst.getOperand(3)); // CondCode TmpInst.addOperand(Inst.getOperand(4)); Inst = TmpInst; @@ -7032,9 +7509,9 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, unsigned Spacing; TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); TmpInst.addOperand(Inst.getOperand(0)); // Vd - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing)); - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing * 2)); TmpInst.addOperand(Inst.getOperand(1)); // Rn TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn @@ -7057,11 +7534,11 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, unsigned Spacing; TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); TmpInst.addOperand(Inst.getOperand(0)); // Vd - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing)); - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing * 2)); - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing * 3)); TmpInst.addOperand(Inst.getOperand(1)); // Rn TmpInst.addOperand(Inst.getOperand(2)); // alignment @@ -7081,16 +7558,16 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, unsigned Spacing; TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); TmpInst.addOperand(Inst.getOperand(0)); // Vd - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing)); - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing * 2)); - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing * 3)); TmpInst.addOperand(Inst.getOperand(1)); // Rn TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn TmpInst.addOperand(Inst.getOperand(2)); // alignment - TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm + TmpInst.addOperand(MCOperand::createReg(0)); // Rm TmpInst.addOperand(Inst.getOperand(3)); // CondCode TmpInst.addOperand(Inst.getOperand(4)); Inst = TmpInst; @@ -7107,11 +7584,11 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, unsigned Spacing; TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); TmpInst.addOperand(Inst.getOperand(0)); // Vd - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing)); - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing * 2)); - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing * 3)); TmpInst.addOperand(Inst.getOperand(1)); // Rn TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn @@ -7134,11 +7611,11 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, unsigned Spacing; TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); TmpInst.addOperand(Inst.getOperand(0)); // Vd - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing)); - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing * 2)); - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing * 3)); TmpInst.addOperand(Inst.getOperand(1)); // Rn TmpInst.addOperand(Inst.getOperand(2)); // alignment @@ -7158,16 +7635,16 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, unsigned Spacing; TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); TmpInst.addOperand(Inst.getOperand(0)); // Vd - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing)); - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing * 2)); - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing * 3)); TmpInst.addOperand(Inst.getOperand(1)); // Rn TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn TmpInst.addOperand(Inst.getOperand(2)); // alignment - TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm + TmpInst.addOperand(MCOperand::createReg(0)); // Rm TmpInst.addOperand(Inst.getOperand(3)); // CondCode TmpInst.addOperand(Inst.getOperand(4)); Inst = TmpInst; @@ -7184,11 +7661,11 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, unsigned Spacing; TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); TmpInst.addOperand(Inst.getOperand(0)); // Vd - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing)); - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing * 2)); - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing * 3)); TmpInst.addOperand(Inst.getOperand(1)); // Rn TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn @@ -7213,9 +7690,9 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, TmpInst.addOperand(Inst.getOperand(1)); // Rn TmpInst.addOperand(Inst.getOperand(2)); // alignment TmpInst.addOperand(Inst.getOperand(0)); // Vd - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing)); - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing * 2)); TmpInst.addOperand(Inst.getOperand(3)); // CondCode TmpInst.addOperand(Inst.getOperand(4)); @@ -7235,11 +7712,11 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, TmpInst.addOperand(Inst.getOperand(1)); // Rn TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn TmpInst.addOperand(Inst.getOperand(2)); // alignment - TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm + TmpInst.addOperand(MCOperand::createReg(0)); // Rm TmpInst.addOperand(Inst.getOperand(0)); // Vd - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing)); - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing * 2)); TmpInst.addOperand(Inst.getOperand(3)); // CondCode TmpInst.addOperand(Inst.getOperand(4)); @@ -7261,9 +7738,9 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, TmpInst.addOperand(Inst.getOperand(2)); // alignment TmpInst.addOperand(Inst.getOperand(3)); // Rm TmpInst.addOperand(Inst.getOperand(0)); // Vd - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing)); - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing * 2)); TmpInst.addOperand(Inst.getOperand(4)); // CondCode TmpInst.addOperand(Inst.getOperand(5)); @@ -7284,11 +7761,11 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, TmpInst.addOperand(Inst.getOperand(1)); // Rn TmpInst.addOperand(Inst.getOperand(2)); // alignment TmpInst.addOperand(Inst.getOperand(0)); // Vd - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing)); - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing * 2)); - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing * 3)); TmpInst.addOperand(Inst.getOperand(3)); // CondCode TmpInst.addOperand(Inst.getOperand(4)); @@ -7308,13 +7785,13 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, TmpInst.addOperand(Inst.getOperand(1)); // Rn TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn TmpInst.addOperand(Inst.getOperand(2)); // alignment - TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm + TmpInst.addOperand(MCOperand::createReg(0)); // Rm TmpInst.addOperand(Inst.getOperand(0)); // Vd - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing)); - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing * 2)); - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing * 3)); TmpInst.addOperand(Inst.getOperand(3)); // CondCode TmpInst.addOperand(Inst.getOperand(4)); @@ -7336,11 +7813,11 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, TmpInst.addOperand(Inst.getOperand(2)); // alignment TmpInst.addOperand(Inst.getOperand(3)); // Rm TmpInst.addOperand(Inst.getOperand(0)); // Vd - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing)); - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing * 2)); - TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() + + TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + Spacing * 3)); TmpInst.addOperand(Inst.getOperand(4)); // CondCode TmpInst.addOperand(Inst.getOperand(5)); @@ -7404,14 +7881,14 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, TmpInst.setOpcode(newOpc); TmpInst.addOperand(Inst.getOperand(0)); // Rd if (isNarrow) - TmpInst.addOperand(MCOperand::CreateReg( + TmpInst.addOperand(MCOperand::createReg( Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0)); TmpInst.addOperand(Inst.getOperand(1)); // Rn TmpInst.addOperand(Inst.getOperand(2)); // Rm TmpInst.addOperand(Inst.getOperand(4)); // CondCode TmpInst.addOperand(Inst.getOperand(5)); if (!isNarrow) - TmpInst.addOperand(MCOperand::CreateReg( + TmpInst.addOperand(MCOperand::createReg( Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0)); Inst = TmpInst; return true; @@ -7441,15 +7918,15 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, TmpInst.setOpcode(newOpc); TmpInst.addOperand(Inst.getOperand(0)); // Rd if (isNarrow) - TmpInst.addOperand(MCOperand::CreateReg( + TmpInst.addOperand(MCOperand::createReg( Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0)); TmpInst.addOperand(Inst.getOperand(1)); // Rn if (newOpc != ARM::t2RRX) - TmpInst.addOperand(MCOperand::CreateImm(Amount)); + TmpInst.addOperand(MCOperand::createImm(Amount)); TmpInst.addOperand(Inst.getOperand(3)); // CondCode TmpInst.addOperand(Inst.getOperand(4)); if (!isNarrow) - TmpInst.addOperand(MCOperand::CreateReg( + TmpInst.addOperand(MCOperand::createReg( Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0)); Inst = TmpInst; return true; @@ -7473,7 +7950,7 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, TmpInst.addOperand(Inst.getOperand(0)); // Rd TmpInst.addOperand(Inst.getOperand(1)); // Rn TmpInst.addOperand(Inst.getOperand(2)); // Rm - TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty + TmpInst.addOperand(MCOperand::createImm(Shifter)); // Shift value and ty TmpInst.addOperand(Inst.getOperand(3)); // CondCode TmpInst.addOperand(Inst.getOperand(4)); TmpInst.addOperand(Inst.getOperand(5)); // cc_out @@ -7504,7 +7981,7 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, TmpInst.addOperand(Inst.getOperand(0)); // Rd TmpInst.addOperand(Inst.getOperand(1)); // Rn if (Opc == ARM::MOVsi) - TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty + TmpInst.addOperand(MCOperand::createImm(Shifter)); // Shift value and ty TmpInst.addOperand(Inst.getOperand(3)); // CondCode TmpInst.addOperand(Inst.getOperand(4)); TmpInst.addOperand(Inst.getOperand(5)); // cc_out @@ -7517,7 +7994,7 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, TmpInst.setOpcode(ARM::MOVsi); TmpInst.addOperand(Inst.getOperand(0)); // Rd TmpInst.addOperand(Inst.getOperand(1)); // Rn - TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty + TmpInst.addOperand(MCOperand::createImm(Shifter)); // Shift value and ty TmpInst.addOperand(Inst.getOperand(2)); // CondCode TmpInst.addOperand(Inst.getOperand(3)); TmpInst.addOperand(Inst.getOperand(4)); // cc_out @@ -7534,7 +8011,7 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, TmpInst.addOperand(Inst.getOperand(4)); // Rt TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb TmpInst.addOperand(Inst.getOperand(1)); // Rn - TmpInst.addOperand(MCOperand::CreateImm(4)); + TmpInst.addOperand(MCOperand::createImm(4)); TmpInst.addOperand(Inst.getOperand(2)); // CondCode TmpInst.addOperand(Inst.getOperand(3)); Inst = TmpInst; @@ -7550,7 +8027,7 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb TmpInst.addOperand(Inst.getOperand(4)); // Rt TmpInst.addOperand(Inst.getOperand(1)); // Rn - TmpInst.addOperand(MCOperand::CreateImm(-4)); + TmpInst.addOperand(MCOperand::createImm(-4)); TmpInst.addOperand(Inst.getOperand(2)); // CondCode TmpInst.addOperand(Inst.getOperand(3)); Inst = TmpInst; @@ -7566,8 +8043,8 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, TmpInst.addOperand(Inst.getOperand(4)); // Rt TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb TmpInst.addOperand(Inst.getOperand(1)); // Rn - TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset - TmpInst.addOperand(MCOperand::CreateImm(4)); + TmpInst.addOperand(MCOperand::createReg(0)); // am2offset + TmpInst.addOperand(MCOperand::createImm(4)); TmpInst.addOperand(Inst.getOperand(2)); // CondCode TmpInst.addOperand(Inst.getOperand(3)); Inst = TmpInst; @@ -7584,7 +8061,7 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb TmpInst.addOperand(Inst.getOperand(4)); // Rt TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12 - TmpInst.addOperand(MCOperand::CreateImm(-4)); + TmpInst.addOperand(MCOperand::createImm(-4)); TmpInst.addOperand(Inst.getOperand(2)); // CondCode TmpInst.addOperand(Inst.getOperand(3)); Inst = TmpInst; @@ -7597,7 +8074,7 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1) break; Inst.setOpcode(ARM::t2ADDri); - Inst.addOperand(MCOperand::CreateReg(0)); // cc_out + Inst.addOperand(MCOperand::createReg(0)); // cc_out break; case ARM::t2SUBri12: // If the immediate fits for encoding T3 (t2SUBri) and the generic "sub" @@ -7606,7 +8083,7 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1) break; Inst.setOpcode(ARM::t2SUBri); - Inst.addOperand(MCOperand::CreateReg(0)); // cc_out + Inst.addOperand(MCOperand::createReg(0)); // cc_out break; case ARM::tADDi8: // If the immediate is in the range 0-7, we want tADDi3 iff Rd was @@ -7658,8 +8135,16 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, // If the destination and first source operand are the same, and // there's no setting of the flags, use encoding T2 instead of T3. // Note that this is only for ADD, not SUB. This mirrors the system - // 'as' behaviour. Make sure the wide encoding wasn't explicit. - if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() || + // 'as' behaviour. Also take advantage of ADD being commutative. + // Make sure the wide encoding wasn't explicit. + bool Swap = false; + auto DestReg = Inst.getOperand(0).getReg(); + bool Transform = DestReg == Inst.getOperand(1).getReg(); + if (!Transform && DestReg == Inst.getOperand(2).getReg()) { + Transform = true; + Swap = true; + } + if (!Transform || Inst.getOperand(5).getReg() != 0 || (static_cast(*Operands[3]).isToken() && static_cast(*Operands[3]).getToken() == ".w")) @@ -7668,7 +8153,7 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, TmpInst.setOpcode(ARM::tADDhirr); TmpInst.addOperand(Inst.getOperand(0)); TmpInst.addOperand(Inst.getOperand(0)); - TmpInst.addOperand(Inst.getOperand(2)); + TmpInst.addOperand(Inst.getOperand(Swap ? 1 : 2)); TmpInst.addOperand(Inst.getOperand(3)); TmpInst.addOperand(Inst.getOperand(4)); Inst = TmpInst; @@ -7679,7 +8164,7 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, // same, we need to use the 32-bit encoding if it's available. if (Inst.getOperand(0).getReg() != Inst.getOperand(2).getReg()) { Inst.setOpcode(ARM::t2ADDrr); - Inst.addOperand(MCOperand::CreateReg(0)); // cc_out + Inst.addOperand(MCOperand::createReg(0)); // cc_out return true; } break; @@ -7732,7 +8217,7 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, // the writeback tied operand. if (hasWritebackToken) Inst.insert(Inst.begin(), - MCOperand::CreateReg(Inst.getOperand(0).getReg())); + MCOperand::createReg(Inst.getOperand(0).getReg())); return true; } break; @@ -7761,8 +8246,8 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, assert (isThumbTwo()); Inst.setOpcode(ARM::t2LDMIA_UPD); // Add the base register and writeback operands. - Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP)); - Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP)); + Inst.insert(Inst.begin(), MCOperand::createReg(ARM::SP)); + Inst.insert(Inst.begin(), MCOperand::createReg(ARM::SP)); return true; } case ARM::tPUSH: { @@ -7772,8 +8257,8 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, assert (isThumbTwo()); Inst.setOpcode(ARM::t2STMDB_UPD); // Add the base register and writeback operands. - Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP)); - Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP)); + Inst.insert(Inst.begin(), MCOperand::createReg(ARM::SP)); + Inst.insert(Inst.begin(), MCOperand::createReg(ARM::SP)); return true; } case ARM::t2MOVi: { @@ -8046,7 +8531,7 @@ unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) { } // Some high-register supporting Thumb1 encodings only allow both registers // to be from r0-r7 when in Thumb2. - else if (Opc == ARM::tADDhirr && isThumbOne() && + else if (Opc == ARM::tADDhirr && isThumbOne() && !hasV6MOps() && isARMLowRegister(Inst.getOperand(1).getReg()) && isARMLowRegister(Inst.getOperand(2).getReg())) return Match_RequiresThumb2; @@ -8064,10 +8549,10 @@ template <> inline bool IsCPSRDead(MCInst *Instr) { } } -static const char *getSubtargetFeatureName(unsigned Val); +static const char *getSubtargetFeatureName(uint64_t Val); bool ARMAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, OperandVector &Operands, - MCStreamer &Out, unsigned &ErrorInfo, + MCStreamer &Out, uint64_t &ErrorInfo, bool MatchingInlineAsm) { MCInst Inst; unsigned MatchResult; @@ -8075,7 +8560,6 @@ bool ARMAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm); switch (MatchResult) { - default: break; case Match_Success: // Context sensitive operand constraints aren't handled by the matcher, // so check them here. @@ -8093,7 +8577,7 @@ bool ARMAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, // encoding is selected. Loop on it while changes happen so the // individual transformations can chain off each other. E.g., // tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8) - while (processInstruction(Inst, Operands)) + while (processInstruction(Inst, Operands, Out)) ; // Only after the instruction is fully processed, we can validate it @@ -8121,7 +8605,7 @@ bool ARMAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, // Special case the error message for the very common case where only // a single subtarget feature is missing (Thumb vs. ARM, e.g.). std::string Msg = "instruction requires:"; - unsigned Mask = 1; + uint64_t Mask = 1; for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) { if (ErrorInfo & Mask) { Msg += " "; @@ -8133,7 +8617,7 @@ bool ARMAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, } case Match_InvalidOperand: { SMLoc ErrorLoc = IDLoc; - if (ErrorInfo != ~0U) { + if (ErrorInfo != ~0ULL) { if (ErrorInfo >= Operands.size()) return Error(IDLoc, "too few operands for instruction"); @@ -8210,6 +8694,7 @@ bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) { const MCObjectFileInfo::Environment Format = getContext().getObjectFileInfo()->getObjectFileType(); bool IsMachO = Format == MCObjectFileInfo::IsMachO; + bool IsCOFF = Format == MCObjectFileInfo::IsCOFF; StringRef IDVal = DirectiveID.getIdentifier(); if (IDVal == ".word") @@ -8261,7 +8746,7 @@ bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) { else if (IDVal == ".thumb_set") return parseDirectiveThumbSet(DirectiveID.getLoc()); - if (!IsMachO) { + if (!IsMachO && !IsCOFF) { if (IDVal == ".arch") return parseDirectiveArch(DirectiveID.getLoc()); else if (IDVal == ".cpu") @@ -8292,6 +8777,7 @@ bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) { /// ::= .short expression [, expression]* /// ::= .word expression [, expression]* bool ARMAsmParser::parseLiteralValues(unsigned Size, SMLoc L) { + MCAsmParser &Parser = getParser(); if (getLexer().isNot(AsmToken::EndOfStatement)) { for (;;) { const MCExpr *Value; @@ -8321,6 +8807,7 @@ bool ARMAsmParser::parseLiteralValues(unsigned Size, SMLoc L) { /// parseDirectiveThumb /// ::= .thumb bool ARMAsmParser::parseDirectiveThumb(SMLoc L) { + MCAsmParser &Parser = getParser(); if (getLexer().isNot(AsmToken::EndOfStatement)) { Error(L, "unexpected token in directive"); return false; @@ -8342,6 +8829,7 @@ bool ARMAsmParser::parseDirectiveThumb(SMLoc L) { /// parseDirectiveARM /// ::= .arm bool ARMAsmParser::parseDirectiveARM(SMLoc L) { + MCAsmParser &Parser = getParser(); if (getLexer().isNot(AsmToken::EndOfStatement)) { Error(L, "unexpected token in directive"); return false; @@ -8370,12 +8858,13 @@ void ARMAsmParser::onLabelParsed(MCSymbol *Symbol) { /// parseDirectiveThumbFunc /// ::= .thumbfunc symbol_name bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) { - const MCAsmInfo *MAI = getParser().getStreamer().getContext().getAsmInfo(); - bool isMachO = MAI->hasSubsectionsViaSymbols(); + MCAsmParser &Parser = getParser(); + const auto Format = getContext().getObjectFileInfo()->getObjectFileType(); + bool IsMachO = Format == MCObjectFileInfo::IsMachO; // Darwin asm has (optionally) function name after .thumb_func direction // ELF doesn't - if (isMachO) { + if (IsMachO) { const AsmToken &Tok = Parser.getTok(); if (Tok.isNot(AsmToken::EndOfStatement)) { if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String)) { @@ -8384,7 +8873,7 @@ bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) { } MCSymbol *Func = - getParser().getContext().GetOrCreateSymbol(Tok.getIdentifier()); + getParser().getContext().getOrCreateSymbol(Tok.getIdentifier()); getParser().getStreamer().EmitThumbFunc(Func); Parser.Lex(); // Consume the identifier token. return false; @@ -8392,7 +8881,8 @@ bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) { } if (getLexer().isNot(AsmToken::EndOfStatement)) { - Error(L, "unexpected token in directive"); + Error(Parser.getTok().getLoc(), "unexpected token in directive"); + Parser.eatToEndOfStatement(); return false; } @@ -8403,6 +8893,7 @@ bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) { /// parseDirectiveSyntax /// ::= .syntax unified | divided bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) { + MCAsmParser &Parser = getParser(); const AsmToken &Tok = Parser.getTok(); if (Tok.isNot(AsmToken::Identifier)) { Error(L, "unexpected token in .syntax directive"); @@ -8434,6 +8925,7 @@ bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) { /// parseDirectiveCode /// ::= .code 16 | 32 bool ARMAsmParser::parseDirectiveCode(SMLoc L) { + MCAsmParser &Parser = getParser(); const AsmToken &Tok = Parser.getTok(); if (Tok.isNot(AsmToken::Integer)) { Error(L, "unexpected token in .code directive"); @@ -8478,6 +8970,7 @@ bool ARMAsmParser::parseDirectiveCode(SMLoc L) { /// parseDirectiveReq /// ::= name .req registername bool ARMAsmParser::parseDirectiveReq(StringRef Name, SMLoc L) { + MCAsmParser &Parser = getParser(); Parser.Lex(); // Eat the '.req' token. unsigned Reg; SMLoc SRegLoc, ERegLoc; @@ -8496,7 +8989,7 @@ bool ARMAsmParser::parseDirectiveReq(StringRef Name, SMLoc L) { Parser.Lex(); // Consume the EndOfStatement - if (RegisterReqs.GetOrCreateValue(Name, Reg).getValue() != Reg) { + if (RegisterReqs.insert(std::make_pair(Name, Reg)).first->second != Reg) { Error(SRegLoc, "redefinition of '" + Name + "' does not match original."); return false; } @@ -8507,6 +9000,7 @@ bool ARMAsmParser::parseDirectiveReq(StringRef Name, SMLoc L) { /// parseDirectiveUneq /// ::= .unreq registername bool ARMAsmParser::parseDirectiveUnreq(SMLoc L) { + MCAsmParser &Parser = getParser(); if (Parser.getTok().isNot(AsmToken::Identifier)) { Parser.eatToEndOfStatement(); Error(L, "unexpected input in .unreq directive."); @@ -8522,15 +9016,9 @@ bool ARMAsmParser::parseDirectiveUnreq(SMLoc L) { bool ARMAsmParser::parseDirectiveArch(SMLoc L) { StringRef Arch = getParser().parseStringToEndOfStatement().trim(); - unsigned ID = StringSwitch(Arch) -#define ARM_ARCH_NAME(NAME, ID, DEFAULT_CPU_NAME, DEFAULT_CPU_ARCH) \ - .Case(NAME, ARM::ID) -#define ARM_ARCH_ALIAS(NAME, ID) \ - .Case(NAME, ARM::ID) -#include "MCTargetDesc/ARMArchName.def" - .Default(ARM::INVALID_ARCH); + unsigned ID = ARMTargetParser::parseArch(Arch); - if (ID == ARM::INVALID_ARCH) { + if (ID == ARM::AK_INVALID) { Error(L, "Unknown arch name"); return false; } @@ -8543,6 +9031,7 @@ bool ARMAsmParser::parseDirectiveArch(SMLoc L) { /// ::= .eabi_attribute int, int [, "str"] /// ::= .eabi_attribute Tag_name, int [, "str"] bool ARMAsmParser::parseDirectiveEabiAttr(SMLoc L) { + MCAsmParser &Parser = getParser(); int64_t Tag; SMLoc TagLoc; TagLoc = Parser.getTok().getLoc(); @@ -8620,8 +9109,13 @@ bool ARMAsmParser::parseDirectiveEabiAttr(SMLoc L) { if (Tag == ARMBuildAttrs::compatibility) { if (Parser.getTok().isNot(AsmToken::Comma)) IsStringValue = false; - else - Parser.Lex(); + if (Parser.getTok().isNot(AsmToken::Comma)) { + Error(Parser.getTok().getLoc(), "comma expected"); + Parser.eatToEndOfStatement(); + return false; + } else { + Parser.Lex(); + } } if (IsStringValue) { @@ -8650,24 +9144,36 @@ bool ARMAsmParser::parseDirectiveEabiAttr(SMLoc L) { bool ARMAsmParser::parseDirectiveCPU(SMLoc L) { StringRef CPU = getParser().parseStringToEndOfStatement().trim(); getTargetStreamer().emitTextAttribute(ARMBuildAttrs::CPU_name, CPU); + + // FIXME: This is using table-gen data, but should be moved to + // ARMTargetParser once that is table-gen'd. + if (!STI.isCPUStringValid(CPU)) { + Error(L, "Unknown CPU name"); + return false; + } + + STI.setDefaultFeatures(CPU); + setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); + return false; } - /// parseDirectiveFPU /// ::= .fpu str bool ARMAsmParser::parseDirectiveFPU(SMLoc L) { + SMLoc FPUNameLoc = getTok().getLoc(); StringRef FPU = getParser().parseStringToEndOfStatement().trim(); - unsigned ID = StringSwitch(FPU) -#define ARM_FPU_NAME(NAME, ID) .Case(NAME, ARM::ID) -#include "ARMFPUName.def" - .Default(ARM::INVALID_FPU); - - if (ID == ARM::INVALID_FPU) { - Error(L, "Unknown FPU name"); + unsigned ID = ARMTargetParser::parseFPU(FPU); + std::vector Features; + if (!ARMTargetParser::getFPUFeatures(ID, Features)) { + Error(FPUNameLoc, "Unknown FPU name"); return false; } + for (auto Feature : Features) + STI.ApplyFeatureFlag(Feature); + setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); + getTargetStreamer().emitFPU(ID); return false; } @@ -8734,6 +9240,7 @@ bool ARMAsmParser::parseDirectiveCantUnwind(SMLoc L) { /// parseDirectivePersonality /// ::= .personality name bool ARMAsmParser::parseDirectivePersonality(SMLoc L) { + MCAsmParser &Parser = getParser(); bool HasExistingPersonality = UC.hasPersonality(); UC.recordPersonality(L); @@ -8769,7 +9276,7 @@ bool ARMAsmParser::parseDirectivePersonality(SMLoc L) { StringRef Name(Parser.getTok().getIdentifier()); Parser.Lex(); - MCSymbol *PR = getParser().getContext().GetOrCreateSymbol(Name); + MCSymbol *PR = getParser().getContext().getOrCreateSymbol(Name); getTargetStreamer().emitPersonality(PR); return false; } @@ -8797,6 +9304,7 @@ bool ARMAsmParser::parseDirectiveHandlerData(SMLoc L) { /// parseDirectiveSetFP /// ::= .setfp fpreg, spreg [, offset] bool ARMAsmParser::parseDirectiveSetFP(SMLoc L) { + MCAsmParser &Parser = getParser(); // Check the ordering of unwind directives if (!UC.hasFnStart()) { Error(L, ".fnstart must precede .setfp directive"); @@ -8874,6 +9382,7 @@ bool ARMAsmParser::parseDirectiveSetFP(SMLoc L) { /// parseDirective /// ::= .pad offset bool ARMAsmParser::parseDirectivePad(SMLoc L) { + MCAsmParser &Parser = getParser(); // Check the ordering of unwind directives if (!UC.hasFnStart()) { Error(L, ".fnstart must precede .pad directive"); @@ -8948,6 +9457,7 @@ bool ARMAsmParser::parseDirectiveRegSave(SMLoc L, bool IsVector) { /// ::= .inst.n opcode [, ...] /// ::= .inst.w opcode [, ...] bool ARMAsmParser::parseDirectiveInst(SMLoc Loc, char Suffix) { + MCAsmParser &Parser = getParser(); int Width; if (isThumb()) { @@ -9044,7 +9554,7 @@ bool ARMAsmParser::parseDirectiveEven(SMLoc L) { } if (!Section) { - getStreamer().InitSections(); + getStreamer().InitSections(false); Section = getStreamer().getCurrentSection().first; } @@ -9060,6 +9570,7 @@ bool ARMAsmParser::parseDirectiveEven(SMLoc L) { /// parseDirectivePersonalityIndex /// ::= .personalityindex index bool ARMAsmParser::parseDirectivePersonalityIndex(SMLoc L) { + MCAsmParser &Parser = getParser(); bool HasExistingPersonality = UC.hasPersonality(); UC.recordPersonalityIndex(L); @@ -9115,6 +9626,7 @@ bool ARMAsmParser::parseDirectivePersonalityIndex(SMLoc L) { /// parseDirectiveUnwindRaw /// ::= .unwind_raw offset, opcode [, opcode...] bool ARMAsmParser::parseDirectiveUnwindRaw(SMLoc L) { + MCAsmParser &Parser = getParser(); if (!UC.hasFnStart()) { Parser.eatToEndOfStatement(); Error(L, ".fnstart must precede .unwind_raw directives"); @@ -9196,6 +9708,8 @@ bool ARMAsmParser::parseDirectiveUnwindRaw(SMLoc L) { /// parseDirectiveTLSDescSeq /// ::= .tlsdescseq tls-variable bool ARMAsmParser::parseDirectiveTLSDescSeq(SMLoc L) { + MCAsmParser &Parser = getParser(); + if (getLexer().isNot(AsmToken::Identifier)) { TokError("expected variable after '.tlsdescseq' directive"); Parser.eatToEndOfStatement(); @@ -9203,7 +9717,7 @@ bool ARMAsmParser::parseDirectiveTLSDescSeq(SMLoc L) { } const MCSymbolRefExpr *SRE = - MCSymbolRefExpr::Create(Parser.getTok().getIdentifier(), + MCSymbolRefExpr::create(Parser.getTok().getIdentifier(), MCSymbolRefExpr::VK_ARM_TLSDESCSEQ, getContext()); Lex(); @@ -9220,6 +9734,7 @@ bool ARMAsmParser::parseDirectiveTLSDescSeq(SMLoc L) { /// parseDirectiveMovSP /// ::= .movsp reg [, #offset] bool ARMAsmParser::parseDirectiveMovSP(SMLoc L) { + MCAsmParser &Parser = getParser(); if (!UC.hasFnStart()) { Parser.eatToEndOfStatement(); Error(L, ".fnstart must precede .movsp directives"); @@ -9283,6 +9798,7 @@ bool ARMAsmParser::parseDirectiveMovSP(SMLoc L) { /// parseDirectiveObjectArch /// ::= .object_arch name bool ARMAsmParser::parseDirectiveObjectArch(SMLoc L) { + MCAsmParser &Parser = getParser(); if (getLexer().isNot(AsmToken::Identifier)) { Error(getLexer().getLoc(), "unexpected token"); Parser.eatToEndOfStatement(); @@ -9293,17 +9809,9 @@ bool ARMAsmParser::parseDirectiveObjectArch(SMLoc L) { SMLoc ArchLoc = Parser.getTok().getLoc(); getLexer().Lex(); - unsigned ID = StringSwitch(Arch) -#define ARM_ARCH_NAME(NAME, ID, DEFAULT_CPU_NAME, DEFAULT_CPU_ARCH) \ - .Case(NAME, ARM::ID) -#define ARM_ARCH_ALIAS(NAME, ID) \ - .Case(NAME, ARM::ID) -#include "MCTargetDesc/ARMArchName.def" -#undef ARM_ARCH_NAME -#undef ARM_ARCH_ALIAS - .Default(ARM::INVALID_ARCH); - - if (ID == ARM::INVALID_ARCH) { + unsigned ID = ARMTargetParser::parseArch(Arch); + + if (ID == ARM::AK_INVALID) { Error(ArchLoc, "unknown architecture '" + Arch + "'"); Parser.eatToEndOfStatement(); return false; @@ -9339,6 +9847,8 @@ bool ARMAsmParser::parseDirectiveAlign(SMLoc L) { /// parseDirectiveThumbSet /// ::= .thumb_set name, value bool ARMAsmParser::parseDirectiveThumbSet(SMLoc L) { + MCAsmParser &Parser = getParser(); + StringRef Name; if (Parser.parseIdentifier(Name)) { TokError("expected identifier after '.thumb_set'"); @@ -9353,22 +9863,13 @@ bool ARMAsmParser::parseDirectiveThumbSet(SMLoc L) { } Lex(); + MCSymbol *Sym; const MCExpr *Value; - if (Parser.parseExpression(Value)) { - TokError("missing expression"); - Parser.eatToEndOfStatement(); - return false; - } - - if (getLexer().isNot(AsmToken::EndOfStatement)) { - TokError("unexpected token"); - Parser.eatToEndOfStatement(); - return false; - } - Lex(); + if (MCParserUtils::parseAssignmentExpression(Name, /* allow_redef */ true, + Parser, Sym, Value)) + return true; - MCSymbol *Alias = getContext().GetOrCreateSymbol(Name); - getTargetStreamer().emitThumbSet(Alias, Value); + getTargetStreamer().emitThumbSet(Sym, Value); return false; } @@ -9385,38 +9886,39 @@ extern "C" void LLVMInitializeARMAsmParser() { #define GET_MATCHER_IMPLEMENTATION #include "ARMGenAsmMatcher.inc" +// FIXME: This structure should be moved inside ARMTargetParser +// when we start to table-generate them, and we can use the ARM +// flags below, that were generated by table-gen. static const struct { - const char *Name; + const unsigned Kind; const unsigned ArchCheck; - const uint64_t Features; + const FeatureBitset Features; } Extensions[] = { - { "crc", Feature_HasV8, ARM::FeatureCRC }, - { "crypto", Feature_HasV8, - ARM::FeatureCrypto | ARM::FeatureNEON | ARM::FeatureFPARMv8 }, - { "fp", Feature_HasV8, ARM::FeatureFPARMv8 }, - { "idiv", Feature_HasV7 | Feature_IsNotMClass, - ARM::FeatureHWDiv | ARM::FeatureHWDivARM }, - // FIXME: iWMMXT not supported - { "iwmmxt", Feature_None, 0 }, - // FIXME: iWMMXT2 not supported - { "iwmmxt2", Feature_None, 0 }, - // FIXME: Maverick not supported - { "maverick", Feature_None, 0 }, - { "mp", Feature_HasV7 | Feature_IsNotMClass, ARM::FeatureMP }, - // FIXME: ARMv6-m OS Extensions feature not checked - { "os", Feature_None, 0 }, + { ARM::AEK_CRC, Feature_HasV8, {ARM::FeatureCRC} }, + { ARM::AEK_CRYPTO, Feature_HasV8, + {ARM::FeatureCrypto, ARM::FeatureNEON, ARM::FeatureFPARMv8} }, + { ARM::AEK_FP, Feature_HasV8, {ARM::FeatureFPARMv8} }, + { (ARM::AEK_HWDIV | ARM::AEK_HWDIVARM), Feature_HasV7 | Feature_IsNotMClass, + {ARM::FeatureHWDiv, ARM::FeatureHWDivARM} }, + { ARM::AEK_MP, Feature_HasV7 | Feature_IsNotMClass, {ARM::FeatureMP} }, + { ARM::AEK_SIMD, Feature_HasV8, {ARM::FeatureNEON, ARM::FeatureFPARMv8} }, // FIXME: Also available in ARMv6-K - { "sec", Feature_HasV7, ARM::FeatureTrustZone }, - { "simd", Feature_HasV8, ARM::FeatureNEON | ARM::FeatureFPARMv8 }, + { ARM::AEK_SEC, Feature_HasV7, {ARM::FeatureTrustZone} }, // FIXME: Only available in A-class, isel not predicated - { "virt", Feature_HasV7, ARM::FeatureVirtualization }, - // FIXME: xscale not supported - { "xscale", Feature_None, 0 }, + { ARM::AEK_VIRT, Feature_HasV7, {ARM::FeatureVirtualization} }, + // FIXME: Unsupported extensions. + { ARM::AEK_OS, Feature_None, {} }, + { ARM::AEK_IWMMXT, Feature_None, {} }, + { ARM::AEK_IWMMXT2, Feature_None, {} }, + { ARM::AEK_MAVERICK, Feature_None, {} }, + { ARM::AEK_XSCALE, Feature_None, {} }, }; /// parseDirectiveArchExtension /// ::= .arch_extension [no]feature bool ARMAsmParser::parseDirectiveArchExtension(SMLoc L) { + MCAsmParser &Parser = getParser(); + if (getLexer().isNot(AsmToken::Identifier)) { Error(getLexer().getLoc(), "unexpected token"); Parser.eatToEndOfStatement(); @@ -9432,12 +9934,15 @@ bool ARMAsmParser::parseDirectiveArchExtension(SMLoc L) { EnableFeature = false; Name = Name.substr(2); } + unsigned FeatureKind = ARMTargetParser::parseArchExt(Name); + if (FeatureKind == ARM::AEK_INVALID) + Error(ExtLoc, "unknown architectural extension: " + Name); for (const auto &Extension : Extensions) { - if (Extension.Name != Name) + if (Extension.Kind != FeatureKind) continue; - if (!Extension.Features) + if (Extension.Features.none()) report_fatal_error("unsupported architectural extension: " + Name); if ((getAvailableFeatures() & Extension.ArchCheck) != Extension.ArchCheck) { @@ -9446,14 +9951,13 @@ bool ARMAsmParser::parseDirectiveArchExtension(SMLoc L) { return false; } - bool ToggleFeatures = EnableFeature - ? (~STI.getFeatureBits() & Extension.Features) - : ( STI.getFeatureBits() & Extension.Features); - if (ToggleFeatures) { - unsigned Features = - ComputeAvailableFeatures(STI.ToggleFeature(Extension.Features)); - setAvailableFeatures(Features); - } + FeatureBitset ToggleFeatures = EnableFeature + ? (~STI.getFeatureBits() & Extension.Features) + : ( STI.getFeatureBits() & Extension.Features); + + uint64_t Features = + ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures)); + setAvailableFeatures(Features); return false; } @@ -9478,11 +9982,11 @@ unsigned ARMAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp, if (CE->getValue() == 0) return Match_Success; break; - case MCK_ARMSOImm: + case MCK_ModImm: if (Op.isImm()) { const MCExpr *SOExpr = Op.getImm(); int64_t Value; - if (!SOExpr->EvaluateAsAbsolute(Value)) + if (!SOExpr->evaluateAsAbsolute(Value)) return Match_Success; assert((Value >= INT32_MIN && Value <= UINT32_MAX) && "expression value must be representable in 32 bits");