}
bool validatetLDMRegList(MCInst Inst, const OperandVector &Operands,
- unsigned ListNo, bool IsPop = false);
+ unsigned ListNo, bool IsARPop = false);
bool validatetSTMRegList(MCInst Inst, const OperandVector &Operands,
unsigned ListNo);
}
bool isAdrLabel() const {
// If we have an immediate that's not a constant, treat it as a label
- // reference needing a fixup. If it is a constant, but it can't fit
- // into shift immediate encoding, we reject it.
- if (isImm() && !isa<MCConstantExpr>(getImm())) return true;
- else return (isARMSOImm() || isARMSOImmNeg());
- }
- bool isARMSOImm() const {
- if (!isImm()) return false;
- const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
- if (!CE) return false;
- int64_t Value = CE->getValue();
- return ARM_AM::getSOImmVal(Value) != -1;
- }
- bool isARMSOImmNot() const {
- if (!isImm()) return false;
- const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
- if (!CE) return false;
- int64_t Value = CE->getValue();
- return ARM_AM::getSOImmVal(~Value) != -1;
- }
- bool isARMSOImmNeg() const {
+ // reference needing a fixup.
+ if (isImm() && !isa<MCConstantExpr>(getImm()))
+ return true;
+
+ // If it is a constant, it must fit into a modified immediate encoding.
if (!isImm()) return false;
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
if (!CE) return false;
int64_t Value = CE->getValue();
- // Only use this when not representable as a plain so_imm.
- return ARM_AM::getSOImmVal(Value) == -1 &&
- ARM_AM::getSOImmVal(-Value) != -1;
+ return (ARM_AM::getSOImmVal(Value) != -1 ||
+ ARM_AM::getSOImmVal(-Value) != -1);;
}
bool isT2SOImm() const {
if (!isImm()) return false;
Inst.addOperand(MCOperand::CreateImm(Memory.OffsetImm->getValue()));
}
- void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
- assert(N == 1 && "Invalid number of operands!");
- // The operand is actually a so_imm, but we have its bitwise
- // negation in the assembly source, so twiddle it here.
- const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
- Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
- }
-
- void addARMSOImmNegOperands(MCInst &Inst, unsigned N) const {
- assert(N == 1 && "Invalid number of operands!");
- // The operand is actually a so_imm, but we have its
- // negation in the assembly source, so twiddle it here.
- const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
- Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
- }
-
void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
return true;
}
+ enum {
+ COFF = (1 << MCObjectFileInfo::IsCOFF),
+ ELF = (1 << MCObjectFileInfo::IsELF),
+ MACHO = (1 << MCObjectFileInfo::IsMachO)
+ };
+ static const struct PrefixEntry {
+ const char *Spelling;
+ ARMMCExpr::VariantKind VariantKind;
+ uint8_t SupportedFormats;
+ } PrefixEntries[] = {
+ { "lower16", ARMMCExpr::VK_ARM_LO16, COFF | ELF | MACHO },
+ { "upper16", ARMMCExpr::VK_ARM_HI16, COFF | ELF | MACHO },
+ };
+
StringRef IDVal = Parser.getTok().getIdentifier();
- if (IDVal == "lower16") {
- RefKind = ARMMCExpr::VK_ARM_LO16;
- } else if (IDVal == "upper16") {
- RefKind = ARMMCExpr::VK_ARM_HI16;
- } else {
+
+ const auto &Prefix =
+ std::find_if(std::begin(PrefixEntries), std::end(PrefixEntries),
+ [&IDVal](const PrefixEntry &PE) {
+ return PE.Spelling == IDVal;
+ });
+ if (Prefix == std::end(PrefixEntries)) {
Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
return true;
}
+
+ uint8_t CurrentFormat;
+ switch (getContext().getObjectFileInfo()->getObjectFileType()) {
+ case MCObjectFileInfo::IsMachO:
+ CurrentFormat = MACHO;
+ break;
+ case MCObjectFileInfo::IsELF:
+ CurrentFormat = ELF;
+ break;
+ case MCObjectFileInfo::IsCOFF:
+ CurrentFormat = COFF;
+ break;
+ }
+
+ if (~Prefix->SupportedFormats & CurrentFormat) {
+ Error(Parser.getTok().getLoc(),
+ "cannot represent relocation in the current file format");
+ return true;
+ }
+
+ RefKind = Prefix->VariantKind;
Parser.Lex();
if (getLexer().isNot(AsmToken::Colon)) {
return true;
}
Parser.Lex(); // Eat the last ':'
+
return false;
}
// conditionally adding the cc_out in the first place because we need
// to check the type of the parsed immediate operand.
if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
- !static_cast<ARMOperand &>(*Operands[4]).isARMSOImm() &&
+ !static_cast<ARMOperand &>(*Operands[4]).isModImm() &&
static_cast<ARMOperand &>(*Operands[4]).isImm0_65535Expr() &&
static_cast<ARMOperand &>(*Operands[1]).getReg() == 0)
return true;
bool ARMAsmParser::validatetLDMRegList(MCInst Inst,
const OperandVector &Operands,
- unsigned ListNo, bool IsPop) {
+ unsigned ListNo, bool IsARPop) {
const ARMOperand &Op = static_cast<const ARMOperand &>(*Operands[ListNo]);
bool HasWritebackToken = Op.isToken() && Op.getToken() == "!";
bool ListContainsLR = listContainsReg(Inst, ListNo, ARM::LR);
bool ListContainsPC = listContainsReg(Inst, ListNo, ARM::PC);
- if (!IsPop && ListContainsSP)
+ if (!IsARPop && ListContainsSP)
return Error(Operands[ListNo + HasWritebackToken]->getStartLoc(),
"SP may not be in the register list");
else if (ListContainsPC && ListContainsLR)
"writeback register not allowed in register list");
if (Opcode == ARM::t2LDMIA_UPD || Opcode == ARM::t2LDMDB_UPD) {
- if (validatetLDMRegList(Inst, Operands, 4))
+ if (validatetLDMRegList(Inst, Operands, 3))
return true;
} else {
- if (validatetSTMRegList(Inst, Operands, 4))
+ if (validatetSTMRegList(Inst, Operands, 3))
return true;
}
break;
!isThumbTwo())
return Error(Operands[2]->getStartLoc(),
"registers must be in range r0-r7 or pc");
- if (validatetLDMRegList(Inst, Operands, 2, /*IsPop=*/true))
+ if (validatetLDMRegList(Inst, Operands, 2, !isMClass()))
return true;
break;
}
MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo,
MatchingInlineAsm);
switch (MatchResult) {
- default: break;
case Match_Success:
// Context sensitive operand constraints aren't handled by the matcher,
// so check them here.
if (Tag == ARMBuildAttrs::compatibility) {
if (Parser.getTok().isNot(AsmToken::Comma))
IsStringValue = false;
- else
- Parser.Lex();
+ if (Parser.getTok().isNot(AsmToken::Comma)) {
+ Error(Parser.getTok().getLoc(), "comma expected");
+ Parser.eatToEndOfStatement();
+ return false;
+ } else {
+ Parser.Lex();
+ }
}
if (IsStringValue) {
// FIXME: This is duplicated in getARMFPUFeatures() in
// tools/clang/lib/Driver/Tools.cpp
static const struct {
- const unsigned Fpu;
+ const unsigned ID;
const uint64_t Enabled;
const uint64_t Disabled;
-} Fpus[] = {
- {ARM::VFP, ARM::FeatureVFP2, ARM::FeatureNEON},
- {ARM::VFPV2, ARM::FeatureVFP2, ARM::FeatureNEON},
- {ARM::VFPV3, ARM::FeatureVFP3, ARM::FeatureNEON},
- {ARM::VFPV3_D16, ARM::FeatureVFP3 | ARM::FeatureD16, ARM::FeatureNEON},
- {ARM::VFPV4, ARM::FeatureVFP4, ARM::FeatureNEON},
- {ARM::VFPV4_D16, ARM::FeatureVFP4 | ARM::FeatureD16, ARM::FeatureNEON},
- {ARM::FPV5_D16, ARM::FeatureFPARMv8 | ARM::FeatureD16,
- ARM::FeatureNEON | ARM::FeatureCrypto},
- {ARM::FP_ARMV8, ARM::FeatureFPARMv8,
- ARM::FeatureNEON | ARM::FeatureCrypto},
- {ARM::NEON, ARM::FeatureNEON, 0},
- {ARM::NEON_VFPV4, ARM::FeatureVFP4 | ARM::FeatureNEON, 0},
- {ARM::NEON_FP_ARMV8, ARM::FeatureFPARMv8 | ARM::FeatureNEON,
- ARM::FeatureCrypto},
- {ARM::CRYPTO_NEON_FP_ARMV8,
- ARM::FeatureFPARMv8 | ARM::FeatureNEON | ARM::FeatureCrypto, 0},
- {ARM::SOFTVFP, 0, 0},
+} FPUs[] = {
+ {ARM::VFP, ARM::FeatureVFP2, ARM::FeatureNEON},
+ {ARM::VFPV2, ARM::FeatureVFP2, ARM::FeatureNEON},
+ {ARM::VFPV3, ARM::FeatureVFP2 | ARM::FeatureVFP3, ARM::FeatureNEON},
+ {ARM::VFPV3_D16, ARM::FeatureVFP2 | ARM::FeatureVFP3 | ARM::FeatureD16,
+ ARM::FeatureNEON},
+ {ARM::VFPV4, ARM::FeatureVFP2 | ARM::FeatureVFP3 | ARM::FeatureVFP4,
+ ARM::FeatureNEON},
+ {ARM::VFPV4_D16,
+ ARM::FeatureVFP2 | ARM::FeatureVFP3 | ARM::FeatureVFP4 | ARM::FeatureD16,
+ ARM::FeatureNEON},
+ {ARM::FPV5_D16, ARM::FeatureVFP2 | ARM::FeatureVFP3 | ARM::FeatureVFP4 |
+ ARM::FeatureFPARMv8 | ARM::FeatureD16,
+ ARM::FeatureNEON | ARM::FeatureCrypto},
+ {ARM::FP_ARMV8, ARM::FeatureVFP2 | ARM::FeatureVFP3 | ARM::FeatureVFP4 |
+ ARM::FeatureFPARMv8,
+ ARM::FeatureNEON | ARM::FeatureCrypto},
+ {ARM::NEON, ARM::FeatureVFP2 | ARM::FeatureVFP3 | ARM::FeatureNEON, 0},
+ {ARM::NEON_VFPV4,
+ ARM::FeatureVFP2 | ARM::FeatureVFP3 | ARM::FeatureVFP4 | ARM::FeatureNEON,
+ 0},
+ {ARM::NEON_FP_ARMV8,
+ ARM::FeatureVFP2 | ARM::FeatureVFP3 | ARM::FeatureVFP4 |
+ ARM::FeatureFPARMv8 | ARM::FeatureNEON,
+ ARM::FeatureCrypto},
+ {ARM::CRYPTO_NEON_FP_ARMV8,
+ ARM::FeatureVFP2 | ARM::FeatureVFP3 | ARM::FeatureVFP4 |
+ ARM::FeatureFPARMv8 | ARM::FeatureNEON | ARM::FeatureCrypto,
+ 0},
+ {ARM::SOFTVFP, 0, 0},
};
/// parseDirectiveFPU
return false;
}
- for (const auto &Fpu : Fpus) {
- if (Fpu.Fpu != ID)
+ for (const auto &Entry : FPUs) {
+ if (Entry.ID != ID)
continue;
// Need to toggle features that should be on but are off and that
// should off but are on.
- uint64_t Toggle = (Fpu.Enabled & ~STI.getFeatureBits()) |
- (Fpu.Disabled & STI.getFeatureBits());
+ uint64_t Toggle = (Entry.Enabled & ~STI.getFeatureBits()) |
+ (Entry.Disabled & STI.getFeatureBits());
setAvailableFeatures(ComputeAvailableFeatures(STI.ToggleFeature(Toggle)));
break;
}
return Match_Success;
break;
case MCK_ModImm:
- case MCK_ARMSOImm:
if (Op.isImm()) {
const MCExpr *SOExpr = Op.getImm();
int64_t Value;