aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Target/ARM/AsmParser
diff options
context:
space:
mode:
authorStephen Hines <srhines@google.com>2013-08-07 15:07:10 -0700
committerStephen Hines <srhines@google.com>2013-08-07 15:07:10 -0700
commitfab2daa4a1127ecb217abe2b07c1769122b6fee1 (patch)
tree268ebfd1963fd98ba412e76819afdf95a7d4267b /lib/Target/ARM/AsmParser
parent8197ac1c1a0a91baa70c4dea8cb488f254ef974c (diff)
parent10251753b6897adcd22cc981c0cc42f348c109de (diff)
downloadexternal_llvm-fab2daa4a1127ecb217abe2b07c1769122b6fee1.zip
external_llvm-fab2daa4a1127ecb217abe2b07c1769122b6fee1.tar.gz
external_llvm-fab2daa4a1127ecb217abe2b07c1769122b6fee1.tar.bz2
Merge commit '10251753b6897adcd22cc981c0cc42f348c109de' into merge-20130807
Conflicts: lib/Archive/ArchiveReader.cpp lib/Support/Unix/PathV2.inc Change-Id: I29d8c1e321a4a380b6013f00bac6a8e4b593cc4e
Diffstat (limited to 'lib/Target/ARM/AsmParser')
-rw-r--r--lib/Target/ARM/AsmParser/ARMAsmParser.cpp614
1 files changed, 216 insertions, 398 deletions
diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
index c59ca64..80e5c6e 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);
}
@@ -216,50 +219,17 @@ class ARMAsmParser : public MCTargetAsmParser {
SMLoc &EndLoc);
// Asm Match Converter Methods
- void cvtT2LdrdPre(MCInst &Inst, const SmallVectorImpl<MCParsedAsmOperand*> &);
- void cvtT2StrdPre(MCInst &Inst, const SmallVectorImpl<MCParsedAsmOperand*> &);
- void cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst,
- const SmallVectorImpl<MCParsedAsmOperand*> &);
- void cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst,
- const SmallVectorImpl<MCParsedAsmOperand*> &);
- void cvtLdWriteBackRegAddrMode2(MCInst &Inst,
- const SmallVectorImpl<MCParsedAsmOperand*> &);
- void cvtLdWriteBackRegAddrModeImm12(MCInst &Inst,
- const SmallVectorImpl<MCParsedAsmOperand*> &);
- void cvtStWriteBackRegAddrModeImm12(MCInst &Inst,
- const SmallVectorImpl<MCParsedAsmOperand*> &);
- void cvtStWriteBackRegAddrMode2(MCInst &Inst,
- const SmallVectorImpl<MCParsedAsmOperand*> &);
- void cvtStWriteBackRegAddrMode3(MCInst &Inst,
- const SmallVectorImpl<MCParsedAsmOperand*> &);
- void cvtLdExtTWriteBackImm(MCInst &Inst,
- const SmallVectorImpl<MCParsedAsmOperand*> &);
- void cvtLdExtTWriteBackReg(MCInst &Inst,
- const SmallVectorImpl<MCParsedAsmOperand*> &);
- void cvtStExtTWriteBackImm(MCInst &Inst,
- const SmallVectorImpl<MCParsedAsmOperand*> &);
- void cvtStExtTWriteBackReg(MCInst &Inst,
- const SmallVectorImpl<MCParsedAsmOperand*> &);
- void cvtLdrdPre(MCInst &Inst, const SmallVectorImpl<MCParsedAsmOperand*> &);
- void cvtStrdPre(MCInst &Inst, const SmallVectorImpl<MCParsedAsmOperand*> &);
- void cvtLdWriteBackRegAddrMode3(MCInst &Inst,
- const SmallVectorImpl<MCParsedAsmOperand*> &);
void cvtThumbMultiply(MCInst &Inst,
const SmallVectorImpl<MCParsedAsmOperand*> &);
- void cvtVLDwbFixed(MCInst &Inst,
- const SmallVectorImpl<MCParsedAsmOperand*> &);
- void cvtVLDwbRegister(MCInst &Inst,
- const SmallVectorImpl<MCParsedAsmOperand*> &);
- void cvtVSTwbFixed(MCInst &Inst,
- const SmallVectorImpl<MCParsedAsmOperand*> &);
- void cvtVSTwbRegister(MCInst &Inst,
- const SmallVectorImpl<MCParsedAsmOperand*> &);
bool validateInstruction(MCInst &Inst,
const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
bool processInstruction(MCInst &Inst,
const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
bool shouldOmitCCOutOperand(StringRef Mnemonic,
SmallVectorImpl<MCParsedAsmOperand*> &Operands);
+ bool shouldOmitPredicateOperand(StringRef Mnemonic,
+ SmallVectorImpl<MCParsedAsmOperand*> &Operands);
+ bool isDeprecated(MCInst &Inst, StringRef &Info);
public:
enum ARMMatchResultTy {
@@ -277,7 +247,7 @@ public:
MCAsmParserExtension::Initialize(_Parser);
// Cache the MCRegisterInfo.
- MRI = &getContext().getRegisterInfo();
+ MRI = getContext().getRegisterInfo();
// Initialize the set of available features.
setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
@@ -626,6 +596,40 @@ 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<unsigned width, unsigned scale>
+ bool isUnsignedOffset() const {
+ if (!isImm()) return false;
+ if (dyn_cast<MCSymbolRefExpr>(Imm.Val)) return true;
+ if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(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;
+ }
+ // 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<MCSymbolRefExpr>(Imm.Val)) return true;
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(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<MCConstantExpr>(getImm());
@@ -1704,6 +1708,37 @@ public:
Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
}
+ void addUnsignedOffset_b8s2Operands(MCInst &Inst, unsigned N) const {
+ if(const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm())) {
+ Inst.addOperand(MCOperand::CreateImm(CE->getValue() >> 2));
+ return;
+ }
+
+ const MCSymbolRefExpr *SR = dyn_cast<MCSymbolRefExpr>(Imm.Val);
+ assert(SR && "Unknown value type!");
+ 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<MCConstantExpr>(getImm());
+ if (CE) {
+ Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
+ return;
+ }
+
+ const MCSymbolRefExpr *SR = dyn_cast<MCSymbolRefExpr>(Imm.Val);
+ assert(SR && "Unknown value type!");
+ Inst.addOperand(MCOperand::CreateExpr(SR));
+ return;
+ }
+
+ assert(isMem() && "Unknown value type!");
+ assert(isa<MCConstantExpr>(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
@@ -2278,21 +2313,24 @@ public:
}
static ARMOperand *
- CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
+ CreateRegList(SmallVectorImpl<std::pair<unsigned, unsigned> > &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<std::pair<unsigned, SMLoc> >::const_iterator
+ for (SmallVectorImpl<std::pair<unsigned, unsigned> >::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;
@@ -2972,12 +3010,14 @@ parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
// The reglist instructions have at most 16 registers, so reserve
// space for that many.
- SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
+ int EReg = 0;
+ SmallVector<std::pair<unsigned, unsigned>, 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<unsigned, SMLoc>(Reg, RegLoc));
+ EReg = MRI->getEncodingValue(Reg);
+ Registers.push_back(std::pair<unsigned, unsigned>(EReg, Reg));
++Reg;
}
const MCRegisterClass *RC;
@@ -2991,7 +3031,8 @@ parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
return Error(RegLoc, "invalid register in register list");
// Store the register.
- Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
+ EReg = MRI->getEncodingValue(Reg);
+ Registers.push_back(std::pair<unsigned, unsigned>(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
@@ -3021,7 +3062,8 @@ parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
// Add all the registers in the range to the register list.
while (Reg != EndReg) {
Reg = getNextRegister(Reg);
- Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
+ EReg = MRI->getEncodingValue(Reg);
+ Registers.push_back(std::pair<unsigned, unsigned>(EReg, Reg));
}
continue;
}
@@ -3054,14 +3096,15 @@ parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &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<unsigned, SMLoc>(Reg, RegLoc));
- if (isQReg)
- Registers.push_back(std::pair<unsigned, SMLoc>(++Reg, RegLoc));
+ EReg = MRI->getEncodingValue(Reg);
+ Registers.push_back(std::pair<unsigned, unsigned>(EReg, Reg));
+ if (isQReg) {
+ EReg = MRI->getEncodingValue(++Reg);
+ Registers.push_back(std::pair<unsigned, unsigned>(EReg, Reg));
+ }
}
if (Parser.getTok().isNot(AsmToken::RCurly))
@@ -4039,260 +4082,9 @@ parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &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<MCParsedAsmOperand*> &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<MCParsedAsmOperand*> &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<MCParsedAsmOperand*> &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<MCParsedAsmOperand*> &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<MCParsedAsmOperand*> &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<MCParsedAsmOperand*> &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<MCParsedAsmOperand*> &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<MCParsedAsmOperand*> &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<MCParsedAsmOperand*> &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<MCParsedAsmOperand*> &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<MCParsedAsmOperand*> &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<MCParsedAsmOperand*> &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<MCParsedAsmOperand*> &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<MCParsedAsmOperand*> &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<MCParsedAsmOperand*> &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<MCParsedAsmOperand*> &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<MCParsedAsmOperand*> &Operands) {
@@ -4310,62 +4102,6 @@ cvtThumbMultiply(MCInst &Inst,
((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
}
-void ARMAsmParser::
-cvtVLDwbFixed(MCInst &Inst,
- const SmallVectorImpl<MCParsedAsmOperand*> &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<MCParsedAsmOperand*> &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<MCParsedAsmOperand*> &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<MCParsedAsmOperand*> &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::
@@ -4869,7 +4605,10 @@ 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 == "vmaxnm" || Mnemonic == "vminnm" ||
+ 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
@@ -4966,28 +4705,30 @@ 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()) ||
- (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") || Mnemonic.startswith("vsel") ||
+ Mnemonic == "vmaxnm" || Mnemonic == "vminnm" || Mnemonic == "vcvta" ||
+ Mnemonic == "vcvtn" || Mnemonic == "vcvtp" || Mnemonic == "vcvtm" ||
+ Mnemonic == "vrinta" || Mnemonic == "vrintn" || Mnemonic == "vrintp" ||
+ Mnemonic == "vrintm") {
+ // 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,
@@ -5042,15 +4783,6 @@ bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
static_cast<ARMOperand*>(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<ARMOperand*>(Operands[3])->getReg()) ||
- !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
- static_cast<ARMOperand*>(Operands[4])->getReg() != ARM::PC &&
- static_cast<ARMOperand*>(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() &&
@@ -5058,6 +4790,11 @@ bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
static_cast<ARMOperand*>(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<ARMOperand*>(Operands[4])->getReg() != ARM::PC &&
+ static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
+ return false;
// Otherwise, we use encoding T4, which does not have a cc_out
// operand.
@@ -5120,6 +4857,34 @@ bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
return false;
}
+bool ARMAsmParser::shouldOmitPredicateOperand(
+ StringRef Mnemonic, SmallVectorImpl<MCParsedAsmOperand *> &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<ARMOperand *>(Operands[2])->getToken() == ".f32") {
+ if (static_cast<ARMOperand *>(Operands[3])->isToken() &&
+ static_cast<ARMOperand *>(Operands[3])->getToken() == ".f32")
+ RegIdx = 4;
+
+ if (static_cast<ARMOperand *>(Operands[RegIdx])->isReg() &&
+ (ARMMCRegisterClasses[ARM::DPRRegClassID]
+ .contains(static_cast<ARMOperand *>(Operands[RegIdx])->getReg()) ||
+ ARMMCRegisterClasses[ARM::QPRRegClassID]
+ .contains(static_cast<ARMOperand *>(Operands[RegIdx])->getReg())))
+ return true;
+ }
+ return false;
+}
+
+bool ARMAsmParser::isDeprecated(MCInst &Inst, StringRef &Info) {
+ if (hasV8Ops() && Inst.getOpcode() == ARM::SETEND) {
+ Info = "armv8";
+ return true;
+ }
+ return false;
+}
+
static bool isDataTypeToken(StringRef Tok) {
return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" ||
Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" ||
@@ -5266,7 +5031,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));
}
@@ -5312,6 +5087,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<ARMOperand*>(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
@@ -5363,6 +5147,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<ARMOperand*>(Operands[3])->isReg() &&
+ static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::PC &&
+ static_cast<ARMOperand*>(Operands[4])->isReg() &&
+ static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::LR &&
+ static_cast<ARMOperand*>(Operands[5])->isImm()) {
+ ARMOperand *Op0 = static_cast<ARMOperand*>(Operands[0]);
+ Operands.erase(Operands.begin());
+ delete Op0;
+ Operands.insert(Operands.begin(), ARMOperand::CreateToken(Name, NameLoc));
+
+ ARMOperand *Op1 = static_cast<ARMOperand*>(Operands[1]);
+ Operands.erase(Operands.begin() + 1);
+ delete Op1;
+ }
return false;
}
@@ -5581,6 +5385,10 @@ validateInstruction(MCInst &Inst,
}
}
+ StringRef DepInfo;
+ if (isDeprecated(Inst, DepInfo))
+ Warning(Loc, "deprecated on " + DepInfo);
+
return false;
}
@@ -5862,7 +5670,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<ARMOperand*>(Operands[2])->isToken() &&
+ static_cast<ARMOperand*>(Operands[2])->getToken() == ".w"))
Inst.setOpcode(ARM::tLDRpci);
else
Inst.setOpcode(ARM::t2LDRpci);
@@ -7851,8 +7661,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;
@@ -8199,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<MCParsedAsmOperand *, 1> Operands;
+ ~CleanupObject() {
+ for (unsigned I = 0, E = Operands.size(); I != E; ++I)
+ delete Operands[I];
+ }
+ } CO;
+
// Parse the register list
- SmallVector<MCParsedAsmOperand*, 1> 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())