X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FARM%2FAsmParser%2FARMAsmParser.cpp;h=afb6e5684dd796e2f648497c8c057ec413754ee2;hb=2bd0118472de352745a2e038245fab4974f7c87e;hp=59e5e84c7e4ce7eba653c13cd1864eb2201634bb;hpb=8adf62034a874adacff158e8adc9438cb3e67c01;p=oota-llvm.git diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 59e5e84c7e4..afb6e5684dd 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -87,10 +87,6 @@ class ARMAsmParser : public MCTargetAsmParser { bool parseMemory(SmallVectorImpl &); bool parseOperand(SmallVectorImpl &, StringRef Mnemonic); bool parsePrefix(ARMMCExpr::VariantKind &RefKind); - const MCExpr *applyPrefixToExpr(const MCExpr *E, - MCSymbolRefExpr::VariantKind Variant); - - bool parseMemRegOffsetShift(ARM_AM::ShiftOpc &ShiftType, unsigned &ShiftAmount); bool parseDirectiveWord(unsigned Size, SMLoc L); @@ -118,10 +114,16 @@ class ARMAsmParser : public MCTargetAsmParser { bool hasV6Ops() const { return STI.getFeatureBits() & ARM::HasV6Ops; } + bool hasV7Ops() const { + return STI.getFeatureBits() & ARM::HasV7Ops; + } void SwitchMode() { unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb)); setAvailableFeatures(FB); } + bool isMClass() const { + return STI.getFeatureBits() & ARM::FeatureMClass; + } /// @name Auto-generated Match Functions /// { @@ -156,6 +158,7 @@ class ARMAsmParser : public MCTargetAsmParser { OperandMatchResultTy parseBitfield(SmallVectorImpl&); OperandMatchResultTy parsePostIdxReg(SmallVectorImpl&); OperandMatchResultTy parseAM3Offset(SmallVectorImpl&); + OperandMatchResultTy parseFPImm(SmallVectorImpl&); // Asm Match Converter Methods bool cvtT2LdrdPre(MCInst &Inst, unsigned Opcode, @@ -164,6 +167,8 @@ class ARMAsmParser : public MCTargetAsmParser { const SmallVectorImpl &); bool cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode, const SmallVectorImpl &); + bool cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode, + const SmallVectorImpl &); bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode, const SmallVectorImpl &); bool cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode, @@ -237,27 +242,29 @@ namespace { /// instruction. class ARMOperand : public MCParsedAsmOperand { enum KindTy { - CondCode, - CCOut, - ITCondMask, - CoprocNum, - CoprocReg, - Immediate, - MemBarrierOpt, - Memory, - PostIndexRegister, - MSRMask, - ProcIFlags, - Register, - RegisterList, - DPRRegisterList, - SPRRegisterList, - ShiftedRegister, - ShiftedImmediate, - ShifterImmediate, - RotateImmediate, - BitfieldDescriptor, - Token + k_CondCode, + k_CCOut, + k_ITCondMask, + k_CoprocNum, + k_CoprocReg, + k_Immediate, + k_FPImmediate, + k_MemBarrierOpt, + k_Memory, + k_PostIndexRegister, + k_MSRMask, + k_ProcIFlags, + k_VectorIndex, + k_Register, + k_RegisterList, + k_DPRRegisterList, + k_SPRRegisterList, + k_ShiftedRegister, + k_ShiftedImmediate, + k_ShifterImmediate, + k_RotateImmediate, + k_BitfieldDescriptor, + k_Token } Kind; SMLoc StartLoc, EndLoc; @@ -297,10 +304,18 @@ class ARMOperand : public MCParsedAsmOperand { unsigned RegNum; } Reg; + struct { + unsigned Val; + } VectorIndex; + struct { const MCExpr *Val; } Imm; + struct { + unsigned Val; // encoded 8-bit representation + } FPImm; + /// Combined record for all forms of ARM address expressions. struct { unsigned BaseRegNum; @@ -309,9 +324,11 @@ class ARMOperand : public MCParsedAsmOperand { const MCConstantExpr *OffsetImm; // Offset immediate value unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg - unsigned ShiftImm; // shift for OffsetReg. + unsigned ShiftImm; // shift for OffsetReg. + unsigned Alignment; // 0 = no alignment specified + // n = alignment in bytes (8, 16, or 32) unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit) - } Mem; + } Memory; struct { unsigned RegNum; @@ -351,61 +368,67 @@ public: StartLoc = o.StartLoc; EndLoc = o.EndLoc; switch (Kind) { - case CondCode: + case k_CondCode: CC = o.CC; break; - case ITCondMask: + case k_ITCondMask: ITMask = o.ITMask; break; - case Token: + case k_Token: Tok = o.Tok; break; - case CCOut: - case Register: + case k_CCOut: + case k_Register: Reg = o.Reg; break; - case RegisterList: - case DPRRegisterList: - case SPRRegisterList: + case k_RegisterList: + case k_DPRRegisterList: + case k_SPRRegisterList: Registers = o.Registers; break; - case CoprocNum: - case CoprocReg: + case k_CoprocNum: + case k_CoprocReg: Cop = o.Cop; break; - case Immediate: + case k_Immediate: Imm = o.Imm; break; - case MemBarrierOpt: + case k_FPImmediate: + FPImm = o.FPImm; + break; + case k_MemBarrierOpt: MBOpt = o.MBOpt; break; - case Memory: - Mem = o.Mem; + case k_Memory: + Memory = o.Memory; break; - case PostIndexRegister: + case k_PostIndexRegister: PostIdxReg = o.PostIdxReg; break; - case MSRMask: + case k_MSRMask: MMask = o.MMask; break; - case ProcIFlags: + case k_ProcIFlags: IFlags = o.IFlags; break; - case ShifterImmediate: + case k_ShifterImmediate: ShifterImm = o.ShifterImm; break; - case ShiftedRegister: + case k_ShiftedRegister: RegShiftedReg = o.RegShiftedReg; break; - case ShiftedImmediate: + case k_ShiftedImmediate: RegShiftedImm = o.RegShiftedImm; break; - case RotateImmediate: + case k_RotateImmediate: RotImm = o.RotImm; break; - case BitfieldDescriptor: + case k_BitfieldDescriptor: Bitfield = o.Bitfield; break; + case k_VectorIndex: + VectorIndex = o.VectorIndex; + break; } } @@ -415,60 +438,71 @@ public: SMLoc getEndLoc() const { return EndLoc; } ARMCC::CondCodes getCondCode() const { - assert(Kind == CondCode && "Invalid access!"); + assert(Kind == k_CondCode && "Invalid access!"); return CC.Val; } unsigned getCoproc() const { - assert((Kind == CoprocNum || Kind == CoprocReg) && "Invalid access!"); + assert((Kind == k_CoprocNum || Kind == k_CoprocReg) && "Invalid access!"); return Cop.Val; } StringRef getToken() const { - assert(Kind == Token && "Invalid access!"); + assert(Kind == k_Token && "Invalid access!"); return StringRef(Tok.Data, Tok.Length); } unsigned getReg() const { - assert((Kind == Register || Kind == CCOut) && "Invalid access!"); + assert((Kind == k_Register || Kind == k_CCOut) && "Invalid access!"); return Reg.RegNum; } const SmallVectorImpl &getRegList() const { - assert((Kind == RegisterList || Kind == DPRRegisterList || - Kind == SPRRegisterList) && "Invalid access!"); + assert((Kind == k_RegisterList || Kind == k_DPRRegisterList || + Kind == k_SPRRegisterList) && "Invalid access!"); return Registers; } const MCExpr *getImm() const { - assert(Kind == Immediate && "Invalid access!"); + assert(Kind == k_Immediate && "Invalid access!"); return Imm.Val; } + unsigned getFPImm() const { + assert(Kind == k_FPImmediate && "Invalid access!"); + return FPImm.Val; + } + + unsigned getVectorIndex() const { + assert(Kind == k_VectorIndex && "Invalid access!"); + return VectorIndex.Val; + } + ARM_MB::MemBOpt getMemBarrierOpt() const { - assert(Kind == MemBarrierOpt && "Invalid access!"); + assert(Kind == k_MemBarrierOpt && "Invalid access!"); return MBOpt.Val; } ARM_PROC::IFlags getProcIFlags() const { - assert(Kind == ProcIFlags && "Invalid access!"); + assert(Kind == k_ProcIFlags && "Invalid access!"); return IFlags.Val; } unsigned getMSRMask() const { - assert(Kind == MSRMask && "Invalid access!"); + assert(Kind == k_MSRMask && "Invalid access!"); return MMask.Val; } - bool isCoprocNum() const { return Kind == CoprocNum; } - bool isCoprocReg() const { return Kind == CoprocReg; } - bool isCondCode() const { return Kind == CondCode; } - bool isCCOut() const { return Kind == CCOut; } - bool isITMask() const { return Kind == ITCondMask; } - bool isITCondCode() const { return Kind == CondCode; } - bool isImm() const { return Kind == Immediate; } + bool isCoprocNum() const { return Kind == k_CoprocNum; } + bool isCoprocReg() const { return Kind == k_CoprocReg; } + bool isCondCode() const { return Kind == k_CondCode; } + bool isCCOut() const { return Kind == k_CCOut; } + bool isITMask() const { return Kind == k_ITCondMask; } + bool isITCondCode() const { return Kind == k_CondCode; } + bool isImm() const { return Kind == k_Immediate; } + bool isFPImm() const { return Kind == k_FPImmediate; } bool isImm8s4() const { - if (Kind != Immediate) + if (Kind != k_Immediate) return false; const MCConstantExpr *CE = dyn_cast(getImm()); if (!CE) return false; @@ -476,7 +510,7 @@ public: return ((Value & 3) == 0) && Value >= -1020 && Value <= 1020; } bool isImm0_1020s4() const { - if (Kind != Immediate) + if (Kind != k_Immediate) return false; const MCConstantExpr *CE = dyn_cast(getImm()); if (!CE) return false; @@ -484,7 +518,7 @@ public: return ((Value & 3) == 0) && Value >= 0 && Value <= 1020; } bool isImm0_508s4() const { - if (Kind != Immediate) + if (Kind != k_Immediate) return false; const MCConstantExpr *CE = dyn_cast(getImm()); if (!CE) return false; @@ -492,7 +526,7 @@ public: return ((Value & 3) == 0) && Value >= 0 && Value <= 508; } bool isImm0_255() const { - if (Kind != Immediate) + if (Kind != k_Immediate) return false; const MCConstantExpr *CE = dyn_cast(getImm()); if (!CE) return false; @@ -500,7 +534,7 @@ public: return Value >= 0 && Value < 256; } bool isImm0_7() const { - if (Kind != Immediate) + if (Kind != k_Immediate) return false; const MCConstantExpr *CE = dyn_cast(getImm()); if (!CE) return false; @@ -508,7 +542,7 @@ public: return Value >= 0 && Value < 8; } bool isImm0_15() const { - if (Kind != Immediate) + if (Kind != k_Immediate) return false; const MCConstantExpr *CE = dyn_cast(getImm()); if (!CE) return false; @@ -516,7 +550,7 @@ public: return Value >= 0 && Value < 16; } bool isImm0_31() const { - if (Kind != Immediate) + if (Kind != k_Immediate) return false; const MCConstantExpr *CE = dyn_cast(getImm()); if (!CE) return false; @@ -524,7 +558,7 @@ public: return Value >= 0 && Value < 32; } bool isImm1_16() const { - if (Kind != Immediate) + if (Kind != k_Immediate) return false; const MCConstantExpr *CE = dyn_cast(getImm()); if (!CE) return false; @@ -532,7 +566,7 @@ public: return Value > 0 && Value < 17; } bool isImm1_32() const { - if (Kind != Immediate) + if (Kind != k_Immediate) return false; const MCConstantExpr *CE = dyn_cast(getImm()); if (!CE) return false; @@ -540,7 +574,7 @@ public: return Value > 0 && Value < 33; } bool isImm0_65535() const { - if (Kind != Immediate) + if (Kind != k_Immediate) return false; const MCConstantExpr *CE = dyn_cast(getImm()); if (!CE) return false; @@ -548,7 +582,7 @@ public: return Value >= 0 && Value < 65536; } bool isImm0_65535Expr() const { - if (Kind != Immediate) + if (Kind != k_Immediate) return false; const MCConstantExpr *CE = dyn_cast(getImm()); // If it's not a constant expression, it'll generate a fixup and be @@ -558,7 +592,7 @@ public: return Value >= 0 && Value < 65536; } bool isImm24bit() const { - if (Kind != Immediate) + if (Kind != k_Immediate) return false; const MCConstantExpr *CE = dyn_cast(getImm()); if (!CE) return false; @@ -566,7 +600,7 @@ public: return Value >= 0 && Value <= 0xffffff; } bool isImmThumbSR() const { - if (Kind != Immediate) + if (Kind != k_Immediate) return false; const MCConstantExpr *CE = dyn_cast(getImm()); if (!CE) return false; @@ -574,7 +608,7 @@ public: return Value > 0 && Value < 33; } bool isPKHLSLImm() const { - if (Kind != Immediate) + if (Kind != k_Immediate) return false; const MCConstantExpr *CE = dyn_cast(getImm()); if (!CE) return false; @@ -582,7 +616,7 @@ public: return Value >= 0 && Value < 32; } bool isPKHASRImm() const { - if (Kind != Immediate) + if (Kind != k_Immediate) return false; const MCConstantExpr *CE = dyn_cast(getImm()); if (!CE) return false; @@ -590,7 +624,7 @@ public: return Value > 0 && Value <= 32; } bool isARMSOImm() const { - if (Kind != Immediate) + if (Kind != k_Immediate) return false; const MCConstantExpr *CE = dyn_cast(getImm()); if (!CE) return false; @@ -598,7 +632,7 @@ public: return ARM_AM::getSOImmVal(Value) != -1; } bool isT2SOImm() const { - if (Kind != Immediate) + if (Kind != k_Immediate) return false; const MCConstantExpr *CE = dyn_cast(getImm()); if (!CE) return false; @@ -606,47 +640,50 @@ public: return ARM_AM::getT2SOImmVal(Value) != -1; } bool isSetEndImm() const { - if (Kind != Immediate) + if (Kind != k_Immediate) return false; const MCConstantExpr *CE = dyn_cast(getImm()); if (!CE) return false; int64_t Value = CE->getValue(); return Value == 1 || Value == 0; } - bool isReg() const { return Kind == Register; } - bool isRegList() const { return Kind == RegisterList; } - bool isDPRRegList() const { return Kind == DPRRegisterList; } - bool isSPRRegList() const { return Kind == SPRRegisterList; } - bool isToken() const { return Kind == Token; } - bool isMemBarrierOpt() const { return Kind == MemBarrierOpt; } - bool isMemory() const { return Kind == Memory; } - bool isShifterImm() const { return Kind == ShifterImmediate; } - bool isRegShiftedReg() const { return Kind == ShiftedRegister; } - bool isRegShiftedImm() const { return Kind == ShiftedImmediate; } - bool isRotImm() const { return Kind == RotateImmediate; } - bool isBitfield() const { return Kind == BitfieldDescriptor; } - bool isPostIdxRegShifted() const { return Kind == PostIndexRegister; } + bool isReg() const { return Kind == k_Register; } + bool isRegList() const { return Kind == k_RegisterList; } + bool isDPRRegList() const { return Kind == k_DPRRegisterList; } + bool isSPRRegList() const { return Kind == k_SPRRegisterList; } + bool isToken() const { return Kind == k_Token; } + bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; } + bool isMemory() const { return Kind == k_Memory; } + bool isShifterImm() const { return Kind == k_ShifterImmediate; } + bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; } + bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; } + bool isRotImm() const { return Kind == k_RotateImmediate; } + bool isBitfield() const { return Kind == k_BitfieldDescriptor; } + bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; } bool isPostIdxReg() const { - return Kind == PostIndexRegister && PostIdxReg.ShiftTy == ARM_AM::no_shift; + return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy == ARM_AM::no_shift; } - bool isMemNoOffset() const { - if (Kind != Memory) + bool isMemNoOffset(bool alignOK = false) const { + if (!isMemory()) return false; // No offset of any kind. - return Mem.OffsetRegNum == 0 && Mem.OffsetImm == 0; + return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 && + (alignOK || Memory.Alignment == 0); + } + bool isAlignedMemory() const { + return isMemNoOffset(true); } bool isAddrMode2() const { - if (Kind != Memory) - return false; + if (!isMemory() || Memory.Alignment != 0) return false; // Check for register offset. - if (Mem.OffsetRegNum) return true; + if (Memory.OffsetRegNum) return true; // Immediate offset in range [-4095, 4095]. - if (!Mem.OffsetImm) return true; - int64_t Val = Mem.OffsetImm->getValue(); + if (!Memory.OffsetImm) return true; + int64_t Val = Memory.OffsetImm->getValue(); return Val > -4096 && Val < 4096; } bool isAM2OffsetImm() const { - if (Kind != Immediate) + if (Kind != k_Immediate) return false; // Immediate offset in range [-4095, 4095]. const MCConstantExpr *CE = dyn_cast(getImm()); @@ -655,21 +692,20 @@ public: return Val > -4096 && Val < 4096; } bool isAddrMode3() const { - if (Kind != Memory) - return false; + if (!isMemory() || Memory.Alignment != 0) return false; // No shifts are legal for AM3. - if (Mem.ShiftType != ARM_AM::no_shift) return false; + if (Memory.ShiftType != ARM_AM::no_shift) return false; // Check for register offset. - if (Mem.OffsetRegNum) return true; + if (Memory.OffsetRegNum) return true; // Immediate offset in range [-255, 255]. - if (!Mem.OffsetImm) return true; - int64_t Val = Mem.OffsetImm->getValue(); + if (!Memory.OffsetImm) return true; + int64_t Val = Memory.OffsetImm->getValue(); return Val > -256 && Val < 256; } bool isAM3Offset() const { - if (Kind != Immediate && Kind != PostIndexRegister) + if (Kind != k_Immediate && Kind != k_PostIndexRegister) return false; - if (Kind == PostIndexRegister) + if (Kind == k_PostIndexRegister) return PostIdxReg.ShiftTy == ARM_AM::no_shift; // Immediate offset in range [-255, 255]. const MCConstantExpr *CE = dyn_cast(getImm()); @@ -679,154 +715,192 @@ public: return (Val > -256 && Val < 256) || Val == INT32_MIN; } bool isAddrMode5() const { - if (Kind != Memory) - return false; + if (!isMemory() || Memory.Alignment != 0) return false; // Check for register offset. - if (Mem.OffsetRegNum) return false; + if (Memory.OffsetRegNum) return false; // Immediate offset in range [-1020, 1020] and a multiple of 4. - if (!Mem.OffsetImm) return true; - int64_t Val = Mem.OffsetImm->getValue(); + if (!Memory.OffsetImm) return true; + int64_t Val = Memory.OffsetImm->getValue(); return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) || Val == INT32_MIN; } + bool isMemTBB() const { + if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative || + Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0) + return false; + return true; + } + bool isMemTBH() const { + if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative || + Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 || + Memory.Alignment != 0 ) + return false; + return true; + } bool isMemRegOffset() const { - if (Kind != Memory || !Mem.OffsetRegNum) + if (!isMemory() || !Memory.OffsetRegNum || Memory.Alignment != 0) return false; return true; } bool isT2MemRegOffset() const { - if (Kind != Memory || !Mem.OffsetRegNum || Mem.isNegative) + if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative || + Memory.Alignment != 0) return false; // Only lsl #{0, 1, 2, 3} allowed. - if (Mem.ShiftType == ARM_AM::no_shift) + if (Memory.ShiftType == ARM_AM::no_shift) return true; - if (Mem.ShiftType != ARM_AM::lsl || Mem.ShiftImm > 3) + if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3) return false; return true; } bool isMemThumbRR() const { // Thumb reg+reg addressing is simple. Just two registers, a base and // an offset. No shifts, negations or any other complicating factors. - if (Kind != Memory || !Mem.OffsetRegNum || Mem.isNegative || - Mem.ShiftType != ARM_AM::no_shift) + if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative || + Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0) return false; - return isARMLowRegister(Mem.BaseRegNum) && - (!Mem.OffsetRegNum || isARMLowRegister(Mem.OffsetRegNum)); + return isARMLowRegister(Memory.BaseRegNum) && + (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum)); } bool isMemThumbRIs4() const { - if (Kind != Memory || Mem.OffsetRegNum != 0 || - !isARMLowRegister(Mem.BaseRegNum)) + if (!isMemory() || Memory.OffsetRegNum != 0 || + !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0) return false; // Immediate offset, multiple of 4 in range [0, 124]. - if (!Mem.OffsetImm) return true; - int64_t Val = Mem.OffsetImm->getValue(); + if (!Memory.OffsetImm) return true; + int64_t Val = Memory.OffsetImm->getValue(); return Val >= 0 && Val <= 124 && (Val % 4) == 0; } bool isMemThumbRIs2() const { - if (Kind != Memory || Mem.OffsetRegNum != 0 || - !isARMLowRegister(Mem.BaseRegNum)) + if (!isMemory() || Memory.OffsetRegNum != 0 || + !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0) return false; // Immediate offset, multiple of 4 in range [0, 62]. - if (!Mem.OffsetImm) return true; - int64_t Val = Mem.OffsetImm->getValue(); + if (!Memory.OffsetImm) return true; + int64_t Val = Memory.OffsetImm->getValue(); return Val >= 0 && Val <= 62 && (Val % 2) == 0; } bool isMemThumbRIs1() const { - if (Kind != Memory || Mem.OffsetRegNum != 0 || - !isARMLowRegister(Mem.BaseRegNum)) + if (!isMemory() || Memory.OffsetRegNum != 0 || + !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0) return false; // Immediate offset in range [0, 31]. - if (!Mem.OffsetImm) return true; - int64_t Val = Mem.OffsetImm->getValue(); + if (!Memory.OffsetImm) return true; + int64_t Val = Memory.OffsetImm->getValue(); return Val >= 0 && Val <= 31; } bool isMemThumbSPI() const { - if (Kind != Memory || Mem.OffsetRegNum != 0 || Mem.BaseRegNum != ARM::SP) + if (!isMemory() || Memory.OffsetRegNum != 0 || + Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0) return false; // Immediate offset, multiple of 4 in range [0, 1020]. - if (!Mem.OffsetImm) return true; - int64_t Val = Mem.OffsetImm->getValue(); + if (!Memory.OffsetImm) return true; + int64_t Val = Memory.OffsetImm->getValue(); return Val >= 0 && Val <= 1020 && (Val % 4) == 0; } bool isMemImm8s4Offset() const { - if (Kind != Memory || Mem.OffsetRegNum != 0) + if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0) return false; // Immediate offset a multiple of 4 in range [-1020, 1020]. - if (!Mem.OffsetImm) return true; - int64_t Val = Mem.OffsetImm->getValue(); + if (!Memory.OffsetImm) return true; + int64_t Val = Memory.OffsetImm->getValue(); return Val >= -1020 && Val <= 1020 && (Val & 3) == 0; } bool isMemImm0_1020s4Offset() const { - if (Kind != Memory || Mem.OffsetRegNum != 0) + if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0) return false; // Immediate offset a multiple of 4 in range [0, 1020]. - if (!Mem.OffsetImm) return true; - int64_t Val = Mem.OffsetImm->getValue(); + if (!Memory.OffsetImm) return true; + int64_t Val = Memory.OffsetImm->getValue(); return Val >= 0 && Val <= 1020 && (Val & 3) == 0; } bool isMemImm8Offset() const { - if (Kind != Memory || Mem.OffsetRegNum != 0) + if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0) return false; // Immediate offset in range [-255, 255]. - if (!Mem.OffsetImm) return true; - int64_t Val = Mem.OffsetImm->getValue(); - return Val > -256 && Val < 256; + if (!Memory.OffsetImm) return true; + int64_t Val = Memory.OffsetImm->getValue(); + return (Val == INT32_MIN) || (Val > -256 && Val < 256); } bool isMemPosImm8Offset() const { - if (Kind != Memory || Mem.OffsetRegNum != 0) + if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0) return false; // Immediate offset in range [0, 255]. - if (!Mem.OffsetImm) return true; - int64_t Val = Mem.OffsetImm->getValue(); + if (!Memory.OffsetImm) return true; + int64_t Val = Memory.OffsetImm->getValue(); return Val >= 0 && Val < 256; } bool isMemNegImm8Offset() const { - if (Kind != Memory || Mem.OffsetRegNum != 0) + if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0) return false; // Immediate offset in range [-255, -1]. - if (!Mem.OffsetImm) return true; - int64_t Val = Mem.OffsetImm->getValue(); + if (!Memory.OffsetImm) return true; + int64_t Val = Memory.OffsetImm->getValue(); return Val > -256 && Val < 0; } bool isMemUImm12Offset() 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, it's something else // and we reject it. - if (Kind == Immediate && !isa(getImm())) + if (Kind == k_Immediate && !isa(getImm())) return true; - if (Kind != Memory || Mem.OffsetRegNum != 0) + if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0) return false; // Immediate offset in range [0, 4095]. - if (!Mem.OffsetImm) return true; - int64_t Val = Mem.OffsetImm->getValue(); + if (!Memory.OffsetImm) return true; + int64_t Val = Memory.OffsetImm->getValue(); return (Val >= 0 && Val < 4096); } bool isMemImm12Offset() 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, it's something else // and we reject it. - if (Kind == Immediate && !isa(getImm())) + if (Kind == k_Immediate && !isa(getImm())) return true; - if (Kind != Memory || Mem.OffsetRegNum != 0) + if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0) return false; // Immediate offset in range [-4095, 4095]. - if (!Mem.OffsetImm) return true; - int64_t Val = Mem.OffsetImm->getValue(); + if (!Memory.OffsetImm) return true; + int64_t Val = Memory.OffsetImm->getValue(); return (Val > -4096 && Val < 4096) || (Val == INT32_MIN); } bool isPostIdxImm8() const { - if (Kind != Immediate) + if (Kind != k_Immediate) return false; const MCConstantExpr *CE = dyn_cast(getImm()); if (!CE) return false; int64_t Val = CE->getValue(); return (Val > -256 && Val < 256) || (Val == INT32_MIN); } + bool isPostIdxImm8s4() const { + if (Kind != k_Immediate) + return false; + const MCConstantExpr *CE = dyn_cast(getImm()); + if (!CE) return false; + int64_t Val = CE->getValue(); + return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) || + (Val == INT32_MIN); + } + + bool isMSRMask() const { return Kind == k_MSRMask; } + bool isProcIFlags() const { return Kind == k_ProcIFlags; } + + bool isVectorIndex8() const { + if (Kind != k_VectorIndex) return false; + return VectorIndex.Val < 8; + } + bool isVectorIndex16() const { + if (Kind != k_VectorIndex) return false; + return VectorIndex.Val < 4; + } + bool isVectorIndex32() const { + if (Kind != k_VectorIndex) return false; + return VectorIndex.Val < 2; + } + - bool isMSRMask() const { return Kind == MSRMask; } - bool isProcIFlags() const { return Kind == ProcIFlags; } void addExpr(MCInst &Inst, const MCExpr *Expr) const { // Add as immediates when possible. Null MCExpr = 0. @@ -936,6 +1010,11 @@ public: addExpr(Inst, getImm()); } + void addFPImmOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + Inst.addOperand(MCOperand::CreateImm(getFPImm())); + } + void addImm8s4Operands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); // FIXME: We really want to scale the value here, but the LDRD/STRD @@ -1056,13 +1135,19 @@ public: void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum)); + Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); + } + + 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)); } void addAddrMode2Operands(MCInst &Inst, unsigned N) const { assert(N == 3 && "Invalid number of operands!"); - int32_t Val = Mem.OffsetImm ? Mem.OffsetImm->getValue() : 0; - if (!Mem.OffsetRegNum) { + int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0; + if (!Memory.OffsetRegNum) { ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add; // Special case for #-0 if (Val == INT32_MIN) Val = 0; @@ -1071,11 +1156,11 @@ public: } else { // For register offset, we encode the shift type and negation flag // here. - Val = ARM_AM::getAM2Opc(Mem.isNegative ? ARM_AM::sub : ARM_AM::add, - Mem.ShiftImm, Mem.ShiftType); + Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, + Memory.ShiftImm, Memory.ShiftType); } - Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum)); - Inst.addOperand(MCOperand::CreateReg(Mem.OffsetRegNum)); + Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); + Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum)); Inst.addOperand(MCOperand::CreateImm(Val)); } @@ -1095,8 +1180,8 @@ public: void addAddrMode3Operands(MCInst &Inst, unsigned N) const { assert(N == 3 && "Invalid number of operands!"); - int32_t Val = Mem.OffsetImm ? Mem.OffsetImm->getValue() : 0; - if (!Mem.OffsetRegNum) { + int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0; + if (!Memory.OffsetRegNum) { ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add; // Special case for #-0 if (Val == INT32_MIN) Val = 0; @@ -1105,16 +1190,16 @@ public: } else { // For register offset, we encode the shift type and negation flag // here. - Val = ARM_AM::getAM3Opc(Mem.isNegative ? ARM_AM::sub : ARM_AM::add, 0); + Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0); } - Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum)); - Inst.addOperand(MCOperand::CreateReg(Mem.OffsetRegNum)); + Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); + Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum)); Inst.addOperand(MCOperand::CreateImm(Val)); } void addAM3OffsetOperands(MCInst &Inst, unsigned N) const { assert(N == 2 && "Invalid number of operands!"); - if (Kind == PostIndexRegister) { + 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)); @@ -1137,35 +1222,35 @@ public: void addAddrMode5Operands(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 = Mem.OffsetImm ? Mem.OffsetImm->getValue() / 4 : 0; + int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0; ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add; // Special case for #-0 if (Val == INT32_MIN) Val = 0; if (Val < 0) Val = -Val; Val = ARM_AM::getAM5Opc(AddSub, Val); - Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum)); + Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); Inst.addOperand(MCOperand::CreateImm(Val)); } void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const { assert(N == 2 && "Invalid number of operands!"); - int64_t Val = Mem.OffsetImm ? Mem.OffsetImm->getValue() : 0; - Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum)); + int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0; + 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 = Mem.OffsetImm ? Mem.OffsetImm->getValue() / 4 : 0; - Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum)); + int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0; + 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 = Mem.OffsetImm ? Mem.OffsetImm->getValue() : 0; - Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum)); + int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0; + Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); Inst.addOperand(MCOperand::CreateImm(Val)); } @@ -1180,80 +1265,92 @@ public: void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const { assert(N == 2 && "Invalid number of operands!"); // If this is an immediate, it's a label reference. - if (Kind == Immediate) { + if (Kind == k_Immediate) { addExpr(Inst, getImm()); Inst.addOperand(MCOperand::CreateImm(0)); return; } // Otherwise, it's a normal memory reg+offset. - int64_t Val = Mem.OffsetImm ? Mem.OffsetImm->getValue() : 0; - Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum)); + int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0; + Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); Inst.addOperand(MCOperand::CreateImm(Val)); } void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const { assert(N == 2 && "Invalid number of operands!"); // If this is an immediate, it's a label reference. - if (Kind == Immediate) { + if (Kind == k_Immediate) { addExpr(Inst, getImm()); Inst.addOperand(MCOperand::CreateImm(0)); return; } // Otherwise, it's a normal memory reg+offset. - int64_t Val = Mem.OffsetImm ? Mem.OffsetImm->getValue() : 0; - Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum)); + int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0; + 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)); + } + + 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)); + } + void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const { assert(N == 3 && "Invalid number of operands!"); - unsigned Val = ARM_AM::getAM2Opc(Mem.isNegative ? ARM_AM::sub : ARM_AM::add, - Mem.ShiftImm, Mem.ShiftType); - Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum)); - Inst.addOperand(MCOperand::CreateReg(Mem.OffsetRegNum)); + 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)); } void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const { assert(N == 3 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum)); - Inst.addOperand(MCOperand::CreateReg(Mem.OffsetRegNum)); - Inst.addOperand(MCOperand::CreateImm(Mem.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(Mem.BaseRegNum)); - Inst.addOperand(MCOperand::CreateReg(Mem.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 = Mem.OffsetImm ? (Mem.OffsetImm->getValue() / 4) : 0; - Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum)); + int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0; + 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 = Mem.OffsetImm ? (Mem.OffsetImm->getValue() / 2) : 0; - Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum)); + int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0; + 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 = Mem.OffsetImm ? (Mem.OffsetImm->getValue()) : 0; - Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum)); + int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0; + 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 = Mem.OffsetImm ? (Mem.OffsetImm->getValue() / 4) : 0; - Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum)); + int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0; + Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); Inst.addOperand(MCOperand::CreateImm(Val)); } @@ -1268,6 +1365,18 @@ public: Inst.addOperand(MCOperand::CreateImm(Imm)); } + void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + const MCConstantExpr *CE = dyn_cast(getImm()); + assert(CE && "non-constant post-idx-imm8s4 operand!"); + int Imm = CE->getValue(); + bool isAdd = Imm >= 0; + 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)); + } + void addPostIdxRegOperands(MCInst &Inst, unsigned N) const { assert(N == 2 && "Invalid number of operands!"); Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum)); @@ -1295,10 +1404,25 @@ public: Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags()))); } + void addVectorIndex8Operands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + Inst.addOperand(MCOperand::CreateImm(getVectorIndex())); + } + + void addVectorIndex16Operands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + Inst.addOperand(MCOperand::CreateImm(getVectorIndex())); + } + + void addVectorIndex32Operands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + Inst.addOperand(MCOperand::CreateImm(getVectorIndex())); + } + virtual void print(raw_ostream &OS) const; static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) { - ARMOperand *Op = new ARMOperand(ITCondMask); + ARMOperand *Op = new ARMOperand(k_ITCondMask); Op->ITMask.Mask = Mask; Op->StartLoc = S; Op->EndLoc = S; @@ -1306,7 +1430,7 @@ public: } static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) { - ARMOperand *Op = new ARMOperand(CondCode); + ARMOperand *Op = new ARMOperand(k_CondCode); Op->CC.Val = CC; Op->StartLoc = S; Op->EndLoc = S; @@ -1314,7 +1438,7 @@ public: } static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) { - ARMOperand *Op = new ARMOperand(CoprocNum); + ARMOperand *Op = new ARMOperand(k_CoprocNum); Op->Cop.Val = CopVal; Op->StartLoc = S; Op->EndLoc = S; @@ -1322,7 +1446,7 @@ public: } static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) { - ARMOperand *Op = new ARMOperand(CoprocReg); + ARMOperand *Op = new ARMOperand(k_CoprocReg); Op->Cop.Val = CopVal; Op->StartLoc = S; Op->EndLoc = S; @@ -1330,7 +1454,7 @@ public: } static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) { - ARMOperand *Op = new ARMOperand(CCOut); + ARMOperand *Op = new ARMOperand(k_CCOut); Op->Reg.RegNum = RegNum; Op->StartLoc = S; Op->EndLoc = S; @@ -1338,7 +1462,7 @@ public: } static ARMOperand *CreateToken(StringRef Str, SMLoc S) { - ARMOperand *Op = new ARMOperand(Token); + ARMOperand *Op = new ARMOperand(k_Token); Op->Tok.Data = Str.data(); Op->Tok.Length = Str.size(); Op->StartLoc = S; @@ -1347,7 +1471,7 @@ public: } static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) { - ARMOperand *Op = new ARMOperand(Register); + ARMOperand *Op = new ARMOperand(k_Register); Op->Reg.RegNum = RegNum; Op->StartLoc = S; Op->EndLoc = E; @@ -1359,7 +1483,7 @@ public: unsigned ShiftReg, unsigned ShiftImm, SMLoc S, SMLoc E) { - ARMOperand *Op = new ARMOperand(ShiftedRegister); + ARMOperand *Op = new ARMOperand(k_ShiftedRegister); Op->RegShiftedReg.ShiftTy = ShTy; Op->RegShiftedReg.SrcReg = SrcReg; Op->RegShiftedReg.ShiftReg = ShiftReg; @@ -1373,7 +1497,7 @@ public: unsigned SrcReg, unsigned ShiftImm, SMLoc S, SMLoc E) { - ARMOperand *Op = new ARMOperand(ShiftedImmediate); + ARMOperand *Op = new ARMOperand(k_ShiftedImmediate); Op->RegShiftedImm.ShiftTy = ShTy; Op->RegShiftedImm.SrcReg = SrcReg; Op->RegShiftedImm.ShiftImm = ShiftImm; @@ -1384,7 +1508,7 @@ public: static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm, SMLoc S, SMLoc E) { - ARMOperand *Op = new ARMOperand(ShifterImmediate); + ARMOperand *Op = new ARMOperand(k_ShifterImmediate); Op->ShifterImm.isASR = isASR; Op->ShifterImm.Imm = Imm; Op->StartLoc = S; @@ -1393,7 +1517,7 @@ public: } static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) { - ARMOperand *Op = new ARMOperand(RotateImmediate); + ARMOperand *Op = new ARMOperand(k_RotateImmediate); Op->RotImm.Imm = Imm; Op->StartLoc = S; Op->EndLoc = E; @@ -1402,7 +1526,7 @@ public: static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width, SMLoc S, SMLoc E) { - ARMOperand *Op = new ARMOperand(BitfieldDescriptor); + ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor); Op->Bitfield.LSB = LSB; Op->Bitfield.Width = Width; Op->StartLoc = S; @@ -1413,13 +1537,13 @@ public: static ARMOperand * CreateRegList(const SmallVectorImpl > &Regs, SMLoc StartLoc, SMLoc EndLoc) { - KindTy Kind = RegisterList; + KindTy Kind = k_RegisterList; if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first)) - Kind = DPRRegisterList; + Kind = k_DPRRegisterList; else if (ARMMCRegisterClasses[ARM::SPRRegClassID]. contains(Regs.front().first)) - Kind = SPRRegisterList; + Kind = k_SPRRegisterList; ARMOperand *Op = new ARMOperand(Kind); for (SmallVectorImpl >::const_iterator @@ -1431,28 +1555,47 @@ public: return Op; } + static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, + MCContext &Ctx) { + ARMOperand *Op = new ARMOperand(k_VectorIndex); + Op->VectorIndex.Val = Idx; + Op->StartLoc = S; + Op->EndLoc = E; + return Op; + } + static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) { - ARMOperand *Op = new ARMOperand(Immediate); + ARMOperand *Op = new ARMOperand(k_Immediate); Op->Imm.Val = Val; Op->StartLoc = S; Op->EndLoc = E; return Op; } + static ARMOperand *CreateFPImm(unsigned Val, SMLoc S, MCContext &Ctx) { + ARMOperand *Op = new ARMOperand(k_FPImmediate); + Op->FPImm.Val = Val; + Op->StartLoc = S; + Op->EndLoc = S; + return Op; + } + static ARMOperand *CreateMem(unsigned BaseRegNum, const MCConstantExpr *OffsetImm, unsigned OffsetRegNum, ARM_AM::ShiftOpc ShiftType, unsigned ShiftImm, + unsigned Alignment, bool isNegative, SMLoc S, SMLoc E) { - ARMOperand *Op = new ARMOperand(Memory); - Op->Mem.BaseRegNum = BaseRegNum; - Op->Mem.OffsetImm = OffsetImm; - Op->Mem.OffsetRegNum = OffsetRegNum; - Op->Mem.ShiftType = ShiftType; - Op->Mem.ShiftImm = ShiftImm; - Op->Mem.isNegative = isNegative; + ARMOperand *Op = new ARMOperand(k_Memory); + Op->Memory.BaseRegNum = BaseRegNum; + Op->Memory.OffsetImm = OffsetImm; + Op->Memory.OffsetRegNum = OffsetRegNum; + Op->Memory.ShiftType = ShiftType; + Op->Memory.ShiftImm = ShiftImm; + Op->Memory.Alignment = Alignment; + Op->Memory.isNegative = isNegative; Op->StartLoc = S; Op->EndLoc = E; return Op; @@ -1462,7 +1605,7 @@ public: ARM_AM::ShiftOpc ShiftTy, unsigned ShiftImm, SMLoc S, SMLoc E) { - ARMOperand *Op = new ARMOperand(PostIndexRegister); + ARMOperand *Op = new ARMOperand(k_PostIndexRegister); Op->PostIdxReg.RegNum = RegNum; Op->PostIdxReg.isAdd = isAdd; Op->PostIdxReg.ShiftTy = ShiftTy; @@ -1473,7 +1616,7 @@ public: } static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) { - ARMOperand *Op = new ARMOperand(MemBarrierOpt); + ARMOperand *Op = new ARMOperand(k_MemBarrierOpt); Op->MBOpt.Val = Opt; Op->StartLoc = S; Op->EndLoc = S; @@ -1481,7 +1624,7 @@ public: } static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) { - ARMOperand *Op = new ARMOperand(ProcIFlags); + ARMOperand *Op = new ARMOperand(k_ProcIFlags); Op->IFlags.Val = IFlags; Op->StartLoc = S; Op->EndLoc = S; @@ -1489,7 +1632,7 @@ public: } static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) { - ARMOperand *Op = new ARMOperand(MSRMask); + ARMOperand *Op = new ARMOperand(k_MSRMask); Op->MMask.Val = MMask; Op->StartLoc = S; Op->EndLoc = S; @@ -1501,13 +1644,17 @@ public: void ARMOperand::print(raw_ostream &OS) const { switch (Kind) { - case CondCode: + case k_FPImmediate: + OS << ""; + break; + case k_CondCode: OS << ""; break; - case CCOut: + case k_CCOut: OS << ""; break; - case ITCondMask: { + case k_ITCondMask: { static char MaskStr[][6] = { "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)", "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)" }; @@ -1515,27 +1662,27 @@ void ARMOperand::print(raw_ostream &OS) const { OS << ""; break; } - case CoprocNum: + case k_CoprocNum: OS << ""; break; - case CoprocReg: + case k_CoprocReg: OS << ""; break; - case MSRMask: + case k_MSRMask: OS << ""; break; - case Immediate: + case k_Immediate: getImm()->print(OS); break; - case MemBarrierOpt: + case k_MemBarrierOpt: OS << ""; break; - case Memory: + case k_Memory: OS << ""; break; - case PostIndexRegister: + case k_PostIndexRegister: OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-") << PostIdxReg.RegNum; if (PostIdxReg.ShiftTy != ARM_AM::no_shift) @@ -1543,7 +1690,7 @@ void ARMOperand::print(raw_ostream &OS) const { << PostIdxReg.ShiftImm; OS << ">"; break; - case ProcIFlags: { + case k_ProcIFlags: { OS << "= 0; --i) @@ -1552,14 +1699,14 @@ void ARMOperand::print(raw_ostream &OS) const { OS << ">"; break; } - case Register: + case k_Register: OS << ""; break; - case ShifterImmediate: + case k_ShifterImmediate: OS << ""; break; - case ShiftedRegister: + case k_ShiftedRegister: OS << ""; break; - case ShiftedImmediate: + case k_ShiftedImmediate: OS << ""; break; - case RotateImmediate: + case k_RotateImmediate: OS << ""; break; - case BitfieldDescriptor: + case k_BitfieldDescriptor: OS << ""; break; - case RegisterList: - case DPRRegisterList: - case SPRRegisterList: { + case k_RegisterList: + case k_DPRRegisterList: + case k_SPRRegisterList: { OS << " &RegList = getRegList(); @@ -1596,9 +1743,12 @@ void ARMOperand::print(raw_ostream &OS) const { OS << ">"; break; } - case Token: + case k_Token: OS << "'" << getToken() << "'"; break; + case k_VectorIndex: + OS << ""; + break; } } @@ -1640,6 +1790,39 @@ int ARMAsmParser::tryParseRegister() { if (!RegNum) return -1; Parser.Lex(); // Eat identifier token. + +#if 0 + // Also check for an index operand. This is only legal for vector registers, + // but that'll get caught OK in operand matching, so we don't need to + // explicitly filter everything else out here. + if (Parser.getTok().is(AsmToken::LBrac)) { + SMLoc SIdx = Parser.getTok().getLoc(); + Parser.Lex(); // Eat left bracket token. + + const MCExpr *ImmVal; + SMLoc ExprLoc = Parser.getTok().getLoc(); + if (getParser().ParseExpression(ImmVal)) + return MatchOperand_ParseFail; + const MCConstantExpr *MCE = dyn_cast(ImmVal); + if (!MCE) { + TokError("immediate value expected for vector index"); + return MatchOperand_ParseFail; + } + + SMLoc E = Parser.getTok().getLoc(); + if (Parser.getTok().isNot(AsmToken::RBrac)) { + Error(E, "']' expected"); + return MatchOperand_ParseFail; + } + + Parser.Lex(); // Eat right bracket token. + + Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(), + SIdx, E, + getContext())); + } +#endif + return RegNum; } @@ -1755,6 +1938,37 @@ tryParseRegisterWithWriteBack(SmallVectorImpl &Operands) { Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(), ExclaimTok.getLoc())); Parser.Lex(); // Eat exclaim token + return false; + } + + // Also check for an index operand. This is only legal for vector registers, + // but that'll get caught OK in operand matching, so we don't need to + // explicitly filter everything else out here. + if (Parser.getTok().is(AsmToken::LBrac)) { + SMLoc SIdx = Parser.getTok().getLoc(); + Parser.Lex(); // Eat left bracket token. + + const MCExpr *ImmVal; + SMLoc ExprLoc = Parser.getTok().getLoc(); + if (getParser().ParseExpression(ImmVal)) + return MatchOperand_ParseFail; + const MCConstantExpr *MCE = dyn_cast(ImmVal); + if (!MCE) { + TokError("immediate value expected for vector index"); + return MatchOperand_ParseFail; + } + + SMLoc E = Parser.getTok().getLoc(); + if (Parser.getTok().isNot(AsmToken::RBrac)) { + Error(E, "']' expected"); + return MatchOperand_ParseFail; + } + + Parser.Lex(); // Eat right bracket token. + + Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(), + SIdx, E, + getContext())); } return false; @@ -2025,20 +2239,24 @@ parseProcIFlagsOperand(SmallVectorImpl &Operands) { assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier"); StringRef IFlagsStr = Tok.getString(); + // An iflags string of "none" is interpreted to mean that none of the AIF + // bits are set. Not a terribly useful instruction, but a valid encoding. unsigned IFlags = 0; - for (int i = 0, e = IFlagsStr.size(); i != e; ++i) { - unsigned Flag = StringSwitch(IFlagsStr.substr(i, 1)) - .Case("a", ARM_PROC::A) - .Case("i", ARM_PROC::I) - .Case("f", ARM_PROC::F) - .Default(~0U); - - // If some specific iflag is already set, it means that some letter is - // present more than once, this is not acceptable. - if (Flag == ~0U || (IFlags & Flag)) - return MatchOperand_NoMatch; + if (IFlagsStr != "none") { + for (int i = 0, e = IFlagsStr.size(); i != e; ++i) { + unsigned Flag = StringSwitch(IFlagsStr.substr(i, 1)) + .Case("a", ARM_PROC::A) + .Case("i", ARM_PROC::I) + .Case("f", ARM_PROC::F) + .Default(~0U); + + // If some specific iflag is already set, it means that some letter is + // present more than once, this is not acceptable. + if (Flag == ~0U || (IFlags & Flag)) + return MatchOperand_NoMatch; - IFlags |= Flag; + IFlags |= Flag; + } } Parser.Lex(); // Eat identifier token. @@ -2054,6 +2272,37 @@ parseMSRMaskOperand(SmallVectorImpl &Operands) { assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier"); StringRef Mask = Tok.getString(); + if (isMClass()) { + // See ARMv6-M 10.1.1 + unsigned FlagsVal = StringSwitch(Mask) + .Case("apsr", 0) + .Case("iapsr", 1) + .Case("eapsr", 2) + .Case("xpsr", 3) + .Case("ipsr", 5) + .Case("epsr", 6) + .Case("iepsr", 7) + .Case("msp", 8) + .Case("psp", 9) + .Case("primask", 16) + .Case("basepri", 17) + .Case("basepri_max", 18) + .Case("faultmask", 19) + .Case("control", 20) + .Default(~0U); + + if (FlagsVal == ~0U) + return MatchOperand_NoMatch; + + if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19) + // basepri, basepri_max and faultmask only valid for V7m. + return MatchOperand_NoMatch; + + Parser.Lex(); // Eat identifier token. + Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S)); + return MatchOperand_Success; + } + // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf" size_t Start = 0, Next = Mask.find('_'); StringRef Flags = ""; @@ -2233,7 +2482,11 @@ parseShifterImm(SmallVectorImpl &Operands) { Error(E, "'asr' shift amount must be in range [1,32]"); return MatchOperand_ParseFail; } - // asr #32 encoded as asr #0. + // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode. + if (isThumb() && Val == 32) { + Error(E, "'asr #32' shift amount not allowed in Thumb mode"); + return MatchOperand_ParseFail; + } if (Val == 32) Val = 0; } else { // Shift amount must be in [1,32] @@ -2256,15 +2509,11 @@ ARMAsmParser::OperandMatchResultTy ARMAsmParser:: parseRotImm(SmallVectorImpl &Operands) { const AsmToken &Tok = Parser.getTok(); SMLoc S = Tok.getLoc(); - if (Tok.isNot(AsmToken::Identifier)) { - Error(S, "rotate operator 'ror' expected"); - return MatchOperand_ParseFail; - } + if (Tok.isNot(AsmToken::Identifier)) + return MatchOperand_NoMatch; StringRef ShiftName = Tok.getString(); - if (ShiftName != "ror" && ShiftName != "ROR") { - Error(S, "rotate operator 'ror' expected"); - return MatchOperand_ParseFail; - } + if (ShiftName != "ror" && ShiftName != "ROR") + return MatchOperand_NoMatch; Parser.Lex(); // Eat the operator. // A '#' and a rotate amount. @@ -2536,6 +2785,20 @@ cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode, return true; } +/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst. +/// Needed here because the Asm Gen Matcher can't handle properly tied operands +/// when they refer multiple MIOperands inside a single one. +bool ARMAsmParser:: +cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode, + const SmallVectorImpl &Operands) { + // Create a writeback register dummy placeholder. + Inst.addOperand(MCOperand::CreateImm(0)); + ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1); + ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2); + ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2); + return true; +} + /// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst. /// Needed here because the Asm Gen Matcher can't handle properly tied operands /// when they refer multiple MIOperands inside a single one. @@ -2793,7 +3056,14 @@ parseMemory(SmallVectorImpl &Operands) { Parser.Lex(); // Eat right bracket token. Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift, - 0, false, S, E)); + 0, 0, false, S, E)); + + // If there's a pre-indexing writeback marker, '!', just add it as a token + // operand. It's rather odd, but syntactically valid. + if (Parser.getTok().is(AsmToken::Exclaim)) { + Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc())); + Parser.Lex(); // Eat the '!'. + } return false; } @@ -2801,7 +3071,54 @@ parseMemory(SmallVectorImpl &Operands) { assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!"); Parser.Lex(); // Eat the comma. - // If we have a '#' it's an immediate offset, else assume it's a register + // If we have a ':', it's an alignment specifier. + if (Parser.getTok().is(AsmToken::Colon)) { + Parser.Lex(); // Eat the ':'. + E = Parser.getTok().getLoc(); + + const MCExpr *Expr; + if (getParser().ParseExpression(Expr)) + return true; + + // The expression has to be a constant. Memory references with relocations + // don't come through here, as they use the