From 99cb622041a0839c7dfcf0263c5102a305a0fdb5 Mon Sep 17 00:00:00 2001 From: Bill Wendling Date: Tue, 18 Jun 2013 07:20:20 +0000 Subject: Use pointers to the MCAsmInfo and MCRegInfo. Someone may want to do something crazy, like replace these objects if they change or something. No functionality change intended. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@184175 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib/Target/ARM/AsmParser') diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index c59ca64..e315d16 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -277,7 +277,7 @@ public: MCAsmParserExtension::Initialize(_Parser); // Cache the MCRegisterInfo. - MRI = &getContext().getRegisterInfo(); + MRI = getContext().getRegisterInfo(); // Initialize the set of available features. setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); @@ -7851,8 +7851,8 @@ bool ARMAsmParser::parseDirectiveARM(SMLoc L) { /// parseDirectiveThumbFunc /// ::= .thumbfunc symbol_name bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) { - const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo(); - bool isMachO = MAI.hasSubsectionsViaSymbols(); + const MCAsmInfo *MAI = getParser().getStreamer().getContext().getAsmInfo(); + bool isMachO = MAI->hasSubsectionsViaSymbols(); StringRef Name; bool needFuncName = true; -- cgit v1.1 From beb920fce6ccc89b4735f280f94cb8c227f4ef5e Mon Sep 17 00:00:00 2001 From: Amaury de la Vieuville Date: Tue, 18 Jun 2013 08:13:05 +0000 Subject: ARM: fix literal load with positive offset encoding When using a positive offset, literal loads where encoded as if it was negative, because: - The sign bit was not assigned to an operand - The addrmode_imm12 operand was not encoding the sign bit correctly This patch also makes the assembler look at the .w/.n specifier for loads. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@184182 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'lib/Target/ARM/AsmParser') diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index e315d16..170d434 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -5862,7 +5862,9 @@ processInstruction(MCInst &Inst, case ARM::t2LDRpcrel: // Select the narrow version if the immediate will fit. if (Inst.getOperand(1).getImm() > 0 && - Inst.getOperand(1).getImm() <= 0xff) + Inst.getOperand(1).getImm() <= 0xff && + !(static_cast(Operands[2])->isToken() && + static_cast(Operands[2])->getToken() == ".w")) Inst.setOpcode(ARM::tLDRpci); else Inst.setOpcode(ARM::t2LDRpci); -- cgit v1.1 From bf811d602d1d81b93846c6cbbd1cec85f2f153cb Mon Sep 17 00:00:00 2001 From: Kevin Enderby Date: Tue, 18 Jun 2013 20:19:24 +0000 Subject: Change the arm assembler to support this from the v7c spec: "When assembling to the ARM instruction set, the .N qualifier produces an assembler error and the .W qualifier has no effect." In the pre-matcher handler in the asm parser the ".w" (wide) qualifier when in ARM mode is now discarded. And an error message is now produced when the ".n" (narrow) qualifier is used in ARM mode. Test cases for these were added. rdar://14064574 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@184224 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'lib/Target/ARM/AsmParser') diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 170d434..647fdb3 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -5266,7 +5266,17 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, doesIgnoreDataTypeSuffix(Mnemonic, ExtraToken)) continue; - if (ExtraToken != ".n") { + // For for ARM mode generate an error if the .n qualifier is used. + if (ExtraToken == ".n" && !isThumb()) { + SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start); + return Error(Loc, "instruction with .n (narrow) qualifier not allowed in " + "arm mode"); + } + + // The .n qualifier is always discarded as that is what the tables + // and matcher expect. In ARM mode the .w qualifier has no effect, + // so discard it to avoid errors that can be caused by the matcher. + if (ExtraToken != ".n" && (isThumb() || ExtraToken != ".w")) { SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start); Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc)); } -- cgit v1.1 From c1a91dd97b000128189421eda6c5bb7905b1f467 Mon Sep 17 00:00:00 2001 From: Tim Northover Date: Wed, 26 Jun 2013 16:52:32 +0000 Subject: ARM: allow predicated barriers in Thumb mode The barrier instructions are only "always-execute" in ARM mode, they can quite happily sit inside an IT block in Thumb. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@184964 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'lib/Target/ARM/AsmParser') diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 647fdb3..f80fba6 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -4966,12 +4966,12 @@ getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet, } else CanAcceptCarrySet = false; - if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" || - Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" || - Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" || - Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" || - Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" || - (Mnemonic == "clrex" && !isThumb()) || + if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "cps" || + Mnemonic == "mcr2" || Mnemonic == "it" || Mnemonic == "mcrr2" || + Mnemonic == "cbz" || Mnemonic == "cdp2" || Mnemonic == "trap" || + Mnemonic == "mrc2" || Mnemonic == "mrrc2" || Mnemonic == "setend" || + ((Mnemonic == "clrex" || Mnemonic == "dmb" || Mnemonic == "dsb" || + Mnemonic == "isb") && !isThumb()) || (Mnemonic == "nop" && isThumbOne()) || ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" || Mnemonic == "ldc2" || Mnemonic == "ldc2l" || -- cgit v1.1 From c19bd321362166805194cbaf170e06a4790d2da9 Mon Sep 17 00:00:00 2001 From: Tim Northover Date: Wed, 26 Jun 2013 16:52:40 +0000 Subject: ARM: fix more cases where predication may or may not be allowed Unfortunately this addresses two issues (by the time I'd disentangled the logic it wasn't worth putting it back to half-broken): + Coprocessor instructions should all be predicable in Thumb mode. + BKPT should never be predicable. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@184965 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 36 +++++++++++++++---------------- 1 file changed, 17 insertions(+), 19 deletions(-) (limited to 'lib/Target/ARM/AsmParser') diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index f80fba6..eda5550 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -4966,28 +4966,26 @@ getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet, } else CanAcceptCarrySet = false; - if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "cps" || - Mnemonic == "mcr2" || Mnemonic == "it" || Mnemonic == "mcrr2" || - Mnemonic == "cbz" || Mnemonic == "cdp2" || Mnemonic == "trap" || - Mnemonic == "mrc2" || Mnemonic == "mrrc2" || Mnemonic == "setend" || - ((Mnemonic == "clrex" || Mnemonic == "dmb" || Mnemonic == "dsb" || - Mnemonic == "isb") && !isThumb()) || - (Mnemonic == "nop" && isThumbOne()) || - ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" || - Mnemonic == "ldc2" || Mnemonic == "ldc2l" || - Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) || - ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) && - !isThumb()) || - Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) { + if (Mnemonic == "bkpt" || Mnemonic == "cbnz" || Mnemonic == "setend" || + Mnemonic == "cps" || Mnemonic == "it" || Mnemonic == "cbz" || + Mnemonic == "trap" || Mnemonic == "setend" || + Mnemonic.startswith("cps")) { + // 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" && + 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"); + } else if (isThumbOne()) { + CanAcceptPredicationCode = Mnemonic != "nop" && Mnemonic != "movs"; } else CanAcceptPredicationCode = true; - - if (isThumb()) { - if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" || - Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp") - CanAcceptPredicationCode = false; - } } bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic, -- cgit v1.1 From 849eedce9921eb8f285cd0df0ad69ee5133459d1 Mon Sep 17 00:00:00 2001 From: Joey Gouly Date: Wed, 26 Jun 2013 16:58:26 +0000 Subject: Add a subtarget feature 'v8' to the ARM backend. This allows for targeting the ARMv8 AArch32 variant. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@184967 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib/Target/ARM/AsmParser') diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index eda5550..ba2bf8e 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -161,6 +161,9 @@ class ARMAsmParser : public MCTargetAsmParser { bool hasV7Ops() const { return STI.getFeatureBits() & ARM::HasV7Ops; } + bool hasV8Ops() const { + return STI.getFeatureBits() & ARM::HasV8Ops; + } bool hasARM() const { return !(STI.getFeatureBits() & ARM::FeatureNoARM); } -- cgit v1.1 From e29e2afc738348c74966ed81b3568779247c9fbd Mon Sep 17 00:00:00 2001 From: Chad Rosier Date: Mon, 1 Jul 2013 20:49:23 +0000 Subject: [ARMAsmParser] Sort the ARM register lists based on the encoding value, not the tablegen enum values. This should be the last fix due to fallout from r185094. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@185379 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 38 +++++++++++++++++++------------ 1 file changed, 23 insertions(+), 15 deletions(-) (limited to 'lib/Target/ARM/AsmParser') diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index ba2bf8e..8595ce3 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -2281,21 +2281,24 @@ public: } static ARMOperand * - CreateRegList(const SmallVectorImpl > &Regs, + CreateRegList(SmallVectorImpl > &Regs, SMLoc StartLoc, SMLoc EndLoc) { + assert (Regs.size() > 0 && "RegList contains no registers?"); KindTy Kind = k_RegisterList; - if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first)) + if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().second)) Kind = k_DPRRegisterList; else if (ARMMCRegisterClasses[ARM::SPRRegClassID]. - contains(Regs.front().first)) + contains(Regs.front().second)) Kind = k_SPRRegisterList; + // Sort based on the register encoding values. + array_pod_sort(Regs.begin(), Regs.end()); + ARMOperand *Op = new ARMOperand(Kind); - for (SmallVectorImpl >::const_iterator + for (SmallVectorImpl >::const_iterator I = Regs.begin(), E = Regs.end(); I != E; ++I) - Op->Registers.push_back(I->first); - array_pod_sort(Op->Registers.begin(), Op->Registers.end()); + Op->Registers.push_back(I->second); Op->StartLoc = StartLoc; Op->EndLoc = EndLoc; return Op; @@ -2975,12 +2978,14 @@ parseRegisterList(SmallVectorImpl &Operands) { // The reglist instructions have at most 16 registers, so reserve // space for that many. - SmallVector, 16> Registers; + int EReg = 0; + SmallVector, 16> Registers; // Allow Q regs and just interpret them as the two D sub-registers. if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) { Reg = getDRegFromQReg(Reg); - Registers.push_back(std::pair(Reg, RegLoc)); + EReg = MRI->getEncodingValue(Reg); + Registers.push_back(std::pair(EReg, Reg)); ++Reg; } const MCRegisterClass *RC; @@ -2994,7 +2999,8 @@ parseRegisterList(SmallVectorImpl &Operands) { return Error(RegLoc, "invalid register in register list"); // Store the register. - Registers.push_back(std::pair(Reg, RegLoc)); + EReg = MRI->getEncodingValue(Reg); + Registers.push_back(std::pair(EReg, Reg)); // This starts immediately after the first register token in the list, // so we can see either a comma or a minus (range separator) as a legal @@ -3024,7 +3030,8 @@ parseRegisterList(SmallVectorImpl &Operands) { // Add all the registers in the range to the register list. while (Reg != EndReg) { Reg = getNextRegister(Reg); - Registers.push_back(std::pair(Reg, RegLoc)); + EReg = MRI->getEncodingValue(Reg); + Registers.push_back(std::pair(EReg, Reg)); } continue; } @@ -3057,14 +3064,15 @@ parseRegisterList(SmallVectorImpl &Operands) { continue; } // VFP register lists must also be contiguous. - // It's OK to use the enumeration values directly here rather, as the - // VFP register classes have the enum sorted properly. if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] && Reg != OldReg + 1) return Error(RegLoc, "non-contiguous register range"); - Registers.push_back(std::pair(Reg, RegLoc)); - if (isQReg) - Registers.push_back(std::pair(++Reg, RegLoc)); + EReg = MRI->getEncodingValue(Reg); + Registers.push_back(std::pair(EReg, Reg)); + if (isQReg) { + EReg = MRI->getEncodingValue(++Reg); + Registers.push_back(std::pair(EReg, Reg)); + } } if (Parser.getTok().isNot(AsmToken::RCurly)) -- cgit v1.1 From b81b477cd4392a51112c3af0659ea9fc176e74f1 Mon Sep 17 00:00:00 2001 From: Mihai Popa Date: Wed, 3 Jul 2013 09:21:44 +0000 Subject: This corrects the implementation of Thumb ADR instruction. There are three issues: 1. it should accept only 4-byte aligned addresses 2. the maximum offset should be 1020 3. it should be encoded with the offset scaled by two bits git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@185528 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'lib/Target/ARM/AsmParser') diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 8595ce3..c270ed0 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -629,6 +629,20 @@ public: bool isITMask() const { return Kind == k_ITCondMask; } bool isITCondCode() const { return Kind == k_CondCode; } bool isImm() const { return Kind == k_Immediate; } + // checks whether this operand is an unsigned offset which fits is a field + // of specified width and scaled by a specific number of bits + template + bool isUnsignedOffset() const { + if (!isImm()) return false; + if (dyn_cast(Imm.Val)) return true; + if (const MCConstantExpr *CE = dyn_cast(Imm.Val)) { + int64_t Val = CE->getValue(); + int64_t Align = 1LL << scale; + int64_t Max = Align * ((1LL << width) - 1); + return ((Val % Align) == 0) && (Val >= 0) && (Val <= Max); + } + return false; + } bool isFPImm() const { if (!isImm()) return false; const MCConstantExpr *CE = dyn_cast(getImm()); @@ -1707,6 +1721,17 @@ public: 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)); + return; + } + + const MCSymbolRefExpr *SR = dyn_cast(Imm.Val); + assert(SR && "Unknown value type!"); + Inst.addOperand(MCOperand::CreateExpr(SR)); + } + 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 -- cgit v1.1 From 79c163d6ddeb84ea1743eca0644688951bfc5a97 Mon Sep 17 00:00:00 2001 From: Tilmann Scheller Date: Wed, 3 Jul 2013 20:38:01 +0000 Subject: ARM: Prevent ARMAsmParser::shouldOmitCCOutOperand() from misidentifying certain Thumb2 add immediate T3 encodings. Before the fix Thumb2 instructions of type "add rD, rN, #imm" (T3 encoding, see ARM ARM A8.8.4) with rD and rN both being low registers (r0-r7) were classified as having the T4 encoding. The T4 encoding doesn't have a cc_out operand so for above instructions the operand gets erroneously removed, corrupting the token stream and leading to parse errors later in the process. This bug prevented "add r1, r7, #0xcbcbcbcb" from being assembled correctly. Fixes . git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@185575 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'lib/Target/ARM/AsmParser') diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index c270ed0..bd4ea53 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -5076,15 +5076,6 @@ bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic, static_cast(Operands[5])->isImm()) { // Nest conditions rather than one big 'if' statement for readability. // - // If either register is a high reg, it's either one of the SP - // variants (handled above) or a 32-bit encoding, so we just - // check against T3. If the second register is the PC, this is an - // alternate form of ADR, which uses encoding T4, so check for that too. - if ((!isARMLowRegister(static_cast(Operands[3])->getReg()) || - !isARMLowRegister(static_cast(Operands[4])->getReg())) && - static_cast(Operands[4])->getReg() != ARM::PC && - static_cast(Operands[5])->isT2SOImm()) - return false; // If both registers are low, we're in an IT block, and the immediate is // in range, we should use encoding T1 instead, which has a cc_out. if (inITBlock() && @@ -5092,6 +5083,11 @@ bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic, isARMLowRegister(static_cast(Operands[4])->getReg()) && static_cast(Operands[5])->isImm0_7()) return false; + // Check against T3. If the second register is the PC, this is an + // alternate form of ADR, which uses encoding T4, so check for that too. + if (static_cast(Operands[4])->getReg() != ARM::PC && + static_cast(Operands[5])->isT2SOImm()) + return false; // Otherwise, we use encoding T4, which does not have a cc_out // operand. -- cgit v1.1 From 4ea250524f77a67102118747dad6ee69f9f3b3aa Mon Sep 17 00:00:00 2001 From: Joey Gouly Date: Thu, 4 Jul 2013 14:57:20 +0000 Subject: Add support for MC assembling and disassembling of vsel{ge, gt, eq, vs} instructions. This adds a new decoder table/namespace 'VFPV8', as these instructions have their top 4 bits as 0b1111, while other Thumb instructions have 0b1110. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@185642 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/Target/ARM/AsmParser') diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index bd4ea53..687ea3f 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -4905,7 +4905,7 @@ StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic, Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" || Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" || Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal" || - Mnemonic == "fmuls") + Mnemonic == "fmuls" || Mnemonic.startswith("vsel")) return Mnemonic; // First, split out any predication code. Ignore mnemonics we know aren't @@ -5005,7 +5005,7 @@ getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet, if (Mnemonic == "bkpt" || Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "cps" || Mnemonic == "it" || Mnemonic == "cbz" || Mnemonic == "trap" || Mnemonic == "setend" || - Mnemonic.startswith("cps")) { + Mnemonic.startswith("cps") || Mnemonic.startswith("vsel")) { // These mnemonics are never predicable CanAcceptPredicationCode = false; } else if (!isThumb()) { -- cgit v1.1 From 2a9683289b78a2533b261e1b341f9ea9724465a0 Mon Sep 17 00:00:00 2001 From: Joey Gouly Date: Sat, 6 Jul 2013 20:50:18 +0000 Subject: Add MC support for the v8fp instructions: vmaxnm and vminnm. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@185767 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'lib/Target/ARM/AsmParser') diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 687ea3f..f7f1901 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -4905,7 +4905,8 @@ StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic, Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" || Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" || Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal" || - Mnemonic == "fmuls" || Mnemonic.startswith("vsel")) + Mnemonic == "fmuls" || Mnemonic == "vmaxnm" || Mnemonic == "vminnm" || + Mnemonic.startswith("vsel")) return Mnemonic; // First, split out any predication code. Ignore mnemonics we know aren't @@ -5005,7 +5006,8 @@ getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet, if (Mnemonic == "bkpt" || Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "cps" || Mnemonic == "it" || Mnemonic == "cbz" || Mnemonic == "trap" || Mnemonic == "setend" || - Mnemonic.startswith("cps") || Mnemonic.startswith("vsel")) { + Mnemonic.startswith("cps") || Mnemonic == "vmaxnm" || + Mnemonic == "vminnm" || Mnemonic.startswith("vsel")) { // These mnemonics are never predicable CanAcceptPredicationCode = false; } else if (!isThumb()) { -- cgit v1.1 From 9fb5a6588becc92be1d7cf503d2947b170be3c31 Mon Sep 17 00:00:00 2001 From: Joey Gouly Date: Tue, 9 Jul 2013 09:59:04 +0000 Subject: Add MC assembly/disassembly support for VCVT{A, N, P, M} to V8FP. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@185922 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'lib/Target/ARM/AsmParser') diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index f7f1901..56557e3 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -4906,7 +4906,8 @@ StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic, Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" || Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal" || Mnemonic == "fmuls" || Mnemonic == "vmaxnm" || Mnemonic == "vminnm" || - Mnemonic.startswith("vsel")) + Mnemonic == "vcvta" || Mnemonic == "vcvtn" || Mnemonic == "vcvtp" || + Mnemonic == "vcvtm" || Mnemonic.startswith("vsel")) return Mnemonic; // First, split out any predication code. Ignore mnemonics we know aren't @@ -5006,8 +5007,9 @@ getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet, if (Mnemonic == "bkpt" || Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "cps" || Mnemonic == "it" || Mnemonic == "cbz" || Mnemonic == "trap" || Mnemonic == "setend" || - Mnemonic.startswith("cps") || Mnemonic == "vmaxnm" || - Mnemonic == "vminnm" || Mnemonic.startswith("vsel")) { + Mnemonic.startswith("cps") || Mnemonic.startswith("vsel") || + Mnemonic == "vmaxnm" || Mnemonic == "vminnm" || Mnemonic == "vcvta" || + Mnemonic == "vcvtn" || Mnemonic == "vcvtp" || Mnemonic == "vcvtm") { // These mnemonics are never predicable CanAcceptPredicationCode = false; } else if (!isThumb()) { -- cgit v1.1 From 12f45c3782c0d01bcf9973bbc23dba2b17ce54cb Mon Sep 17 00:00:00 2001 From: Joey Gouly Date: Tue, 9 Jul 2013 11:26:18 +0000 Subject: Add MC assembly/disassembly support for VRINT{A, N, P, M} to V8FP. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@185929 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'lib/Target/ARM/AsmParser') diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 56557e3..f114b7a 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -4906,8 +4906,9 @@ StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic, Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" || Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal" || Mnemonic == "fmuls" || Mnemonic == "vmaxnm" || Mnemonic == "vminnm" || - Mnemonic == "vcvta" || Mnemonic == "vcvtn" || Mnemonic == "vcvtp" || - Mnemonic == "vcvtm" || Mnemonic.startswith("vsel")) + Mnemonic == "vcvta" || Mnemonic == "vcvtn" || Mnemonic == "vcvtp" || + Mnemonic == "vcvtm" || Mnemonic == "vrinta" || Mnemonic == "vrintn" || + Mnemonic == "vrintp" || Mnemonic == "vrintm" || Mnemonic.startswith("vsel")) return Mnemonic; // First, split out any predication code. Ignore mnemonics we know aren't @@ -5009,7 +5010,9 @@ getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet, Mnemonic == "trap" || Mnemonic == "setend" || Mnemonic.startswith("cps") || Mnemonic.startswith("vsel") || Mnemonic == "vmaxnm" || Mnemonic == "vminnm" || Mnemonic == "vcvta" || - Mnemonic == "vcvtn" || Mnemonic == "vcvtp" || Mnemonic == "vcvtm") { + Mnemonic == "vcvtn" || Mnemonic == "vcvtp" || Mnemonic == "vcvtm" || + Mnemonic == "vrinta" || Mnemonic == "vrintn" || Mnemonic == "vrintp" || + Mnemonic == "vrintm") { // These mnemonics are never predicable CanAcceptPredicationCode = false; } else if (!isThumb()) { -- cgit v1.1 From 6fec715a1a662ce3b560f85c710875cfeeb1fb98 Mon Sep 17 00:00:00 2001 From: Joey Gouly Date: Fri, 19 Jul 2013 16:34:16 +0000 Subject: [ARMv8] Implement the NEON instructions VRINT{N, X, A, Z, M, P}. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@186688 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'lib/Target/ARM/AsmParser') diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index f114b7a..7061ede 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -263,6 +263,8 @@ class ARMAsmParser : public MCTargetAsmParser { const SmallVectorImpl &Ops); bool shouldOmitCCOutOperand(StringRef Mnemonic, SmallVectorImpl &Operands); + bool shouldOmitPredicateOperand(StringRef Mnemonic, + SmallVectorImpl &Operands); public: enum ARMMatchResultTy { @@ -5157,6 +5159,25 @@ bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic, return false; } +bool ARMAsmParser::shouldOmitPredicateOperand( + StringRef Mnemonic, SmallVectorImpl &Operands) { + // VRINT{Z, R, X} have a predicate operand in VFP, but not in NEON + unsigned RegIdx = 3; + if ((Mnemonic == "vrintz" || Mnemonic == "vrintx" || Mnemonic == "vrintr") && + static_cast(Operands[2])->getToken() == ".f32") { + if (static_cast(Operands[3])->isToken() && + static_cast(Operands[3])->getToken() == ".f32") + RegIdx = 4; + + if (static_cast(Operands[RegIdx])->isReg() && + (ARMMCRegisterClasses[ARM::DPRRegClassID] + .contains(static_cast(Operands[RegIdx])->getReg()) || + ARMMCRegisterClasses[ARM::QPRRegClassID] + .contains(static_cast(Operands[RegIdx])->getReg()))) + return true; + } +} + static bool isDataTypeToken(StringRef Tok) { return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" || Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" || @@ -5359,6 +5380,15 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, delete Op; } + // Some instructions have the same mnemonic, but don't always + // have a predicate. Distinguish them here and delete the + // predicate if needed. + if (shouldOmitPredicateOperand(Mnemonic, Operands)) { + ARMOperand *Op = static_cast(Operands[1]); + Operands.erase(Operands.begin() + 1); + delete Op; + } + // ARM mode 'blx' need special handling, as the register operand version // is predicable, but the label operand version is not. So, we can't rely // on the Mnemonic based checking to correctly figure out when to put -- cgit v1.1 From 55dcefbc4006204c0d2816d5a7c921517c53383c Mon Sep 17 00:00:00 2001 From: Joey Gouly Date: Fri, 19 Jul 2013 16:45:16 +0000 Subject: Add a line that got missed off somehow. Sorry about that! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@186692 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'lib/Target/ARM/AsmParser') diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 7061ede..e10d2c7 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -5176,6 +5176,7 @@ bool ARMAsmParser::shouldOmitPredicateOperand( .contains(static_cast(Operands[RegIdx])->getReg()))) return true; } + return false; } static bool isDataTypeToken(StringRef Tok) { -- cgit v1.1 From 1c6e6ce10c61f8db656a04af36e2b374c0fe9566 Mon Sep 17 00:00:00 2001 From: Tim Northover Date: Mon, 22 Jul 2013 09:06:12 +0000 Subject: ARM: remove now unneeded custom Asm converters After Ulrich's r180677 (thanks!) TableGen is intelligent enough to handle tied constraints involving complex operands properly, so virtually all of the ARM custom converters are now unnecessary. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@186810 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 349 +----------------------------- 1 file changed, 3 insertions(+), 346 deletions(-) (limited to 'lib/Target/ARM/AsmParser') diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index e10d2c7..fc1faff 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -219,44 +219,8 @@ class ARMAsmParser : public MCTargetAsmParser { SMLoc &EndLoc); // Asm Match Converter Methods - void cvtT2LdrdPre(MCInst &Inst, const SmallVectorImpl &); - void cvtT2StrdPre(MCInst &Inst, const SmallVectorImpl &); - void cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, - const SmallVectorImpl &); - void cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, - const SmallVectorImpl &); - void cvtLdWriteBackRegAddrMode2(MCInst &Inst, - const SmallVectorImpl &); - void cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, - const SmallVectorImpl &); - void cvtStWriteBackRegAddrModeImm12(MCInst &Inst, - const SmallVectorImpl &); - void cvtStWriteBackRegAddrMode2(MCInst &Inst, - const SmallVectorImpl &); - void cvtStWriteBackRegAddrMode3(MCInst &Inst, - const SmallVectorImpl &); - void cvtLdExtTWriteBackImm(MCInst &Inst, - const SmallVectorImpl &); - void cvtLdExtTWriteBackReg(MCInst &Inst, - const SmallVectorImpl &); - void cvtStExtTWriteBackImm(MCInst &Inst, - const SmallVectorImpl &); - void cvtStExtTWriteBackReg(MCInst &Inst, - const SmallVectorImpl &); - void cvtLdrdPre(MCInst &Inst, const SmallVectorImpl &); - void cvtStrdPre(MCInst &Inst, const SmallVectorImpl &); - void cvtLdWriteBackRegAddrMode3(MCInst &Inst, - const SmallVectorImpl &); void cvtThumbMultiply(MCInst &Inst, const SmallVectorImpl &); - void cvtVLDwbFixed(MCInst &Inst, - const SmallVectorImpl &); - void cvtVLDwbRegister(MCInst &Inst, - const SmallVectorImpl &); - void cvtVSTwbFixed(MCInst &Inst, - const SmallVectorImpl &); - void cvtVSTwbRegister(MCInst &Inst, - const SmallVectorImpl &); bool validateInstruction(MCInst &Inst, const SmallVectorImpl &Ops); bool processInstruction(MCInst &Inst, @@ -4077,260 +4041,9 @@ parseAM3Offset(SmallVectorImpl &Operands) { return MatchOperand_Success; } -/// cvtT2LdrdPre - 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. -void ARMAsmParser:: -cvtT2LdrdPre(MCInst &Inst, - const SmallVectorImpl &Operands) { - // Rt, Rt2 - ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1); - ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1); - // Create a writeback register dummy placeholder. - Inst.addOperand(MCOperand::CreateReg(0)); - // addr - ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2); - // pred - ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2); -} - -/// cvtT2StrdPre - 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. -void ARMAsmParser:: -cvtT2StrdPre(MCInst &Inst, - const SmallVectorImpl &Operands) { - // Create a writeback register dummy placeholder. - Inst.addOperand(MCOperand::CreateReg(0)); - // Rt, Rt2 - ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1); - ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1); - // addr - ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2); - // pred - ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2); -} - -/// cvtLdWriteBackRegT2AddrModeImm8 - 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. -void ARMAsmParser:: -cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, - const SmallVectorImpl &Operands) { - ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1); - - // Create a writeback register dummy placeholder. - Inst.addOperand(MCOperand::CreateImm(0)); - - ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2); - ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2); -} - -/// 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. -void ARMAsmParser:: -cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, - 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); -} - -/// 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. -void ARMAsmParser:: -cvtLdWriteBackRegAddrMode2(MCInst &Inst, - const SmallVectorImpl &Operands) { - ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1); - - // Create a writeback register dummy placeholder. - Inst.addOperand(MCOperand::CreateImm(0)); - - ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3); - ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2); -} - -/// cvtLdWriteBackRegAddrModeImm12 - 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. -void ARMAsmParser:: -cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, - const SmallVectorImpl &Operands) { - ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1); - - // Create a writeback register dummy placeholder. - Inst.addOperand(MCOperand::CreateImm(0)); - - ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2); - ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2); -} - - -/// cvtStWriteBackRegAddrModeImm12 - 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. -void ARMAsmParser:: -cvtStWriteBackRegAddrModeImm12(MCInst &Inst, - const SmallVectorImpl &Operands) { - // Create a writeback register dummy placeholder. - Inst.addOperand(MCOperand::CreateImm(0)); - ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1); - ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2); - ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2); -} - -/// cvtStWriteBackRegAddrMode2 - 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. -void ARMAsmParser:: -cvtStWriteBackRegAddrMode2(MCInst &Inst, - const SmallVectorImpl &Operands) { - // Create a writeback register dummy placeholder. - Inst.addOperand(MCOperand::CreateImm(0)); - ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1); - ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3); - ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2); -} - -/// cvtStWriteBackRegAddrMode3 - 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. -void ARMAsmParser:: -cvtStWriteBackRegAddrMode3(MCInst &Inst, - const SmallVectorImpl &Operands) { - // Create a writeback register dummy placeholder. - Inst.addOperand(MCOperand::CreateImm(0)); - ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1); - ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3); - ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2); -} - -/// cvtLdExtTWriteBackImm - 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. -void ARMAsmParser:: -cvtLdExtTWriteBackImm(MCInst &Inst, - const SmallVectorImpl &Operands) { - // Rt - ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1); - // Create a writeback register dummy placeholder. - Inst.addOperand(MCOperand::CreateImm(0)); - // addr - ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1); - // offset - ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1); - // pred - ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2); -} - -/// cvtLdExtTWriteBackReg - 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. -void ARMAsmParser:: -cvtLdExtTWriteBackReg(MCInst &Inst, - const SmallVectorImpl &Operands) { - // Rt - ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1); - // Create a writeback register dummy placeholder. - Inst.addOperand(MCOperand::CreateImm(0)); - // addr - ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1); - // offset - ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2); - // pred - ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2); -} - -/// cvtStExtTWriteBackImm - 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. -void ARMAsmParser:: -cvtStExtTWriteBackImm(MCInst &Inst, - const SmallVectorImpl &Operands) { - // Create a writeback register dummy placeholder. - Inst.addOperand(MCOperand::CreateImm(0)); - // Rt - ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1); - // addr - ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1); - // offset - ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1); - // pred - ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2); -} - -/// cvtStExtTWriteBackReg - 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. -void ARMAsmParser:: -cvtStExtTWriteBackReg(MCInst &Inst, - const SmallVectorImpl &Operands) { - // Create a writeback register dummy placeholder. - Inst.addOperand(MCOperand::CreateImm(0)); - // Rt - ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1); - // addr - ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1); - // offset - ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2); - // pred - ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2); -} - -/// cvtLdrdPre - 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. -void ARMAsmParser:: -cvtLdrdPre(MCInst &Inst, - const SmallVectorImpl &Operands) { - // Rt, Rt2 - ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1); - ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1); - // Create a writeback register dummy placeholder. - Inst.addOperand(MCOperand::CreateImm(0)); - // addr - ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3); - // pred - ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2); -} - -/// cvtStrdPre - 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. -void ARMAsmParser:: -cvtStrdPre(MCInst &Inst, - const SmallVectorImpl &Operands) { - // Create a writeback register dummy placeholder. - Inst.addOperand(MCOperand::CreateImm(0)); - // Rt, Rt2 - ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1); - ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1); - // addr - ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3); - // pred - ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2); -} - -/// cvtLdWriteBackRegAddrMode3 - 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. -void ARMAsmParser:: -cvtLdWriteBackRegAddrMode3(MCInst &Inst, - const SmallVectorImpl &Operands) { - ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1); - // Create a writeback register dummy placeholder. - Inst.addOperand(MCOperand::CreateImm(0)); - ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3); - ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2); -} - -/// cvtThumbMultiply - 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. +/// Convert parsed operands to MCInst. Needed here because this instruction +/// only has two register operands, but multiplication is commutative so +/// assemblers should accept both "mul rD, rN, rD" and "mul rD, rD, rN". void ARMAsmParser:: cvtThumbMultiply(MCInst &Inst, const SmallVectorImpl &Operands) { @@ -4348,62 +4061,6 @@ cvtThumbMultiply(MCInst &Inst, ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2); } -void ARMAsmParser:: -cvtVLDwbFixed(MCInst &Inst, - const SmallVectorImpl &Operands) { - // Vd - ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1); - // Create a writeback register dummy placeholder. - Inst.addOperand(MCOperand::CreateImm(0)); - // Vn - ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2); - // pred - ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2); -} - -void ARMAsmParser:: -cvtVLDwbRegister(MCInst &Inst, - const SmallVectorImpl &Operands) { - // Vd - ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1); - // Create a writeback register dummy placeholder. - Inst.addOperand(MCOperand::CreateImm(0)); - // Vn - ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2); - // Vm - ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1); - // pred - ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2); -} - -void ARMAsmParser:: -cvtVSTwbFixed(MCInst &Inst, - const SmallVectorImpl &Operands) { - // Create a writeback register dummy placeholder. - Inst.addOperand(MCOperand::CreateImm(0)); - // Vn - ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2); - // Vt - ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1); - // pred - ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2); -} - -void ARMAsmParser:: -cvtVSTwbRegister(MCInst &Inst, - const SmallVectorImpl &Operands) { - // Create a writeback register dummy placeholder. - Inst.addOperand(MCOperand::CreateImm(0)); - // Vn - ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2); - // Vm - ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1); - // Vt - ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1); - // pred - ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2); -} - /// 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:: -- cgit v1.1 From 02265382929b0275d7b7b334eab5e2fd34e1b9fe Mon Sep 17 00:00:00 2001 From: Mihai Popa Date: Mon, 22 Jul 2013 15:49:36 +0000 Subject: This adds range checking for "ldr Rn, [pc, #imm]" Thumb instructions. With this patch: 1. ldr.n is recognized as mnemonic for the short encoding 2. ldr.w is recognized as menmonic for the long encoding 3. ldr will map to either short or long encodings depending on the size of the offset git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@186831 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 40 +++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) (limited to 'lib/Target/ARM/AsmParser') diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index fc1faff..6d885a0 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -609,6 +609,26 @@ public: } return false; } + // checks whether this operand is a memory operand computed as an offset + // applied to PC. the offset may have 8 bits of magnitude and is represented + // with two bits of shift. textually it may be either [pc, #imm], #imm or + // relocable expression... + bool isThumbMemPC() const { + int64_t Val = 0; + if (isImm()) { + if (isa(Imm.Val)) return true; + const MCConstantExpr *CE = dyn_cast(Imm.Val); + if (!CE) return false; + Val = CE->getValue(); + } + else if (isMem()) { + if(!Memory.OffsetImm || Memory.OffsetRegNum) return false; + if(Memory.BaseRegNum != ARM::PC) return false; + Val = Memory.OffsetImm->getValue(); + } + else return false; + return ((Val % 4) == 0) && (Val >= -1020) && (Val <= 1020); + } bool isFPImm() const { if (!isImm()) return false; const MCConstantExpr *CE = dyn_cast(getImm()); @@ -1698,6 +1718,26 @@ public: Inst.addOperand(MCOperand::CreateExpr(SR)); } + void addThumbMemPCOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + if (isImm()) { + const MCConstantExpr *CE = dyn_cast(getImm()); + if (CE) { + Inst.addOperand(MCOperand::CreateImm(CE->getValue())); + return; + } + + const MCSymbolRefExpr *SR = dyn_cast(Imm.Val); + assert(SR && "Unknown value type!"); + 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 -- cgit v1.1 From e38070fc32818a6e412dafbb8b3807b413d0819e Mon Sep 17 00:00:00 2001 From: Kevin Enderby Date: Wed, 31 Jul 2013 21:05:30 +0000 Subject: Added the B9.3.19 SUBS PC, LR, #imm (Thumb2) system instruction. While the .td entry is nice and all, it takes a pretty gross hack in ARMAsmParser::ParseInstruction() because of handling of other "subs" instructions to get it to match. Ran it by Jim Grosbach and he said it was about what he expected to make this work given the existing code. rdar://14214063 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@187530 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'lib/Target/ARM/AsmParser') diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 6d885a0..8e56a1a 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -5138,6 +5138,26 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, } } + // FIXME: As said above, this is all a pretty gross hack. This instruction + // does not fit with other "subs" and tblgen. + // Adjust operands of B9.3.19 SUBS PC, LR, #imm (Thumb2) system instruction + // so the Mnemonic is the original name "subs" and delete the predicate + // operand so it will match the table entry. + if (isThumbTwo() && Mnemonic == "sub" && Operands.size() == 6 && + static_cast(Operands[3])->isReg() && + static_cast(Operands[3])->getReg() == ARM::PC && + static_cast(Operands[4])->isReg() && + static_cast(Operands[4])->getReg() == ARM::LR && + static_cast(Operands[5])->isImm()) { + ARMOperand *Op0 = static_cast(Operands[0]); + Operands.erase(Operands.begin()); + delete Op0; + Operands.insert(Operands.begin(), ARMOperand::CreateToken(Name, NameLoc)); + + ARMOperand *Op1 = static_cast(Operands[1]); + Operands.erase(Operands.begin() + 1); + delete Op1; + } return false; } -- cgit v1.1 From 787fdb86a71c5108c231b3bbbb7d3fea3ce4bb8c Mon Sep 17 00:00:00 2001 From: Joey Gouly Date: Fri, 2 Aug 2013 19:18:12 +0000 Subject: [ARMv8] Add an assembler warning for the deprecated 'setend' instruction. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@187666 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'lib/Target/ARM/AsmParser') diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 8e56a1a..862e116 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -229,6 +229,7 @@ class ARMAsmParser : public MCTargetAsmParser { SmallVectorImpl &Operands); bool shouldOmitPredicateOperand(StringRef Mnemonic, SmallVectorImpl &Operands); + bool isDeprecated(MCInst &Inst, StringRef &Info); public: enum ARMMatchResultTy { @@ -4876,6 +4877,13 @@ bool ARMAsmParser::shouldOmitPredicateOperand( return false; } +bool ARMAsmParser::isDeprecated(MCInst &Inst, StringRef &Info) { + if (hasV8Ops() && Inst.getOpcode() == ARM::SETEND) { + Info = "armv8"; + return true; + } +} + static bool isDataTypeToken(StringRef Tok) { return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" || Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" || @@ -5376,6 +5384,10 @@ validateInstruction(MCInst &Inst, } } + StringRef DepInfo; + if (isDeprecated(Inst, DepInfo)) + Warning(Loc, "deprecated on " + DepInfo); + return false; } -- cgit v1.1 From e7bc73b8d127e0e17ba6ac7ceb7462134c730f68 Mon Sep 17 00:00:00 2001 From: Joey Gouly Date: Fri, 2 Aug 2013 20:50:01 +0000 Subject: Add a missing 'return' statement. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@187671 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'lib/Target/ARM/AsmParser') diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 862e116..c2f6bf3 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -4882,6 +4882,7 @@ bool ARMAsmParser::isDeprecated(MCInst &Inst, StringRef &Info) { Info = "armv8"; return true; } + return false; } static bool isDataTypeToken(StringRef Tok) { -- cgit v1.1 From 527692a59442345afc662488c68d4f9d9e468da9 Mon Sep 17 00:00:00 2001 From: Benjamin Kramer Date: Sat, 3 Aug 2013 22:16:24 +0000 Subject: ARMAsmParser: Plug a leak. Using an object to do the cleanup may look like overkill, but it's safer and nicer than putting deletes everywhere. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@187696 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'lib/Target/ARM/AsmParser') diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index c2f6bf3..80e5c6e 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -8009,11 +8009,19 @@ bool ARMAsmParser::parseDirectiveRegSave(SMLoc L, bool IsVector) { if (HandlerDataLoc.isValid()) return Error(L, ".save or .vsave must precede .handlerdata directive"); + // RAII object to make sure parsed operands are deleted. + struct CleanupObject { + SmallVector Operands; + ~CleanupObject() { + for (unsigned I = 0, E = Operands.size(); I != E; ++I) + delete Operands[I]; + } + } CO; + // Parse the register list - SmallVector Operands; - if (parseRegisterList(Operands)) + if (parseRegisterList(CO.Operands)) return true; - ARMOperand *Op = (ARMOperand*)Operands[0]; + ARMOperand *Op = (ARMOperand*)CO.Operands[0]; if (!IsVector && !Op->isRegList()) return Error(L, ".save expects GPR registers"); if (IsVector && !Op->isDPRRegList()) -- cgit v1.1