summaryrefslogtreecommitdiff
path: root/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2021-07-29 20:15:26 +0000
committerDimitry Andric <dim@FreeBSD.org>2021-07-29 20:15:26 +0000
commit344a3780b2e33f6ca763666c380202b18aab72a3 (patch)
treef0b203ee6eb71d7fdd792373e3c81eb18d6934dd /llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
parentb60736ec1405bb0a8dd40989f67ef4c93da068ab (diff)
Diffstat (limited to 'llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp')
-rw-r--r--llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp638
1 files changed, 416 insertions, 222 deletions
diff --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
index 52577d75ddf5..e410fe0aeff2 100644
--- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
+++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
@@ -32,7 +32,6 @@
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstrDesc.h"
#include "llvm/MC/MCInstrInfo.h"
-#include "llvm/MC/MCObjectFileInfo.h"
#include "llvm/MC/MCParser/MCAsmLexer.h"
#include "llvm/MC/MCParser/MCAsmParser.h"
#include "llvm/MC/MCParser/MCAsmParserExtension.h"
@@ -500,6 +499,7 @@ class ARMAsmParser : public MCTargetAsmParser {
StringRef FullInst, bool &CanAcceptCarrySet,
bool &CanAcceptPredicationCode,
bool &CanAcceptVPTPredicationCode);
+ bool enableArchExtFeature(StringRef Name, SMLoc &ExtLoc);
void tryConvertingToTwoOperandForm(StringRef Mnemonic, bool CarrySetting,
OperandVector &Operands);
@@ -847,7 +847,7 @@ class ARMOperand : public MCParsedAsmOperand {
unsigned BaseRegNum;
// Offset is in OffsetReg or OffsetImm. If both are zero, no offset
// was specified.
- const MCConstantExpr *OffsetImm; // Offset immediate value
+ const MCExpr *OffsetImm; // Offset immediate value
unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL
ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg
unsigned ShiftImm; // shift for OffsetReg.
@@ -1107,7 +1107,10 @@ public:
else if (isGPRMem()) {
if(!Memory.OffsetImm || Memory.OffsetRegNum) return false;
if(Memory.BaseRegNum != ARM::PC) return false;
- Val = Memory.OffsetImm->getValue();
+ if (const auto *CE = dyn_cast<MCConstantExpr>(Memory.OffsetImm))
+ Val = CE->getValue();
+ else
+ return false;
}
else return false;
return ((Val % 4) == 0) && (Val >= 0) && (Val <= 1020);
@@ -1496,9 +1499,12 @@ public:
return false;
// Immediate offset in range [-4095, 4095].
if (!Memory.OffsetImm) return true;
- int64_t Val = Memory.OffsetImm->getValue();
- return (Val > -4096 && Val < 4096) ||
- (Val == std::numeric_limits<int32_t>::min());
+ if (const auto *CE = dyn_cast<MCConstantExpr>(Memory.OffsetImm)) {
+ int64_t Val = CE->getValue();
+ return (Val > -4096 && Val < 4096) ||
+ (Val == std::numeric_limits<int32_t>::min());
+ }
+ return false;
}
bool isAlignedMemory() const {
@@ -1581,8 +1587,11 @@ public:
if (Memory.OffsetRegNum) return true;
// Immediate offset in range [-4095, 4095].
if (!Memory.OffsetImm) return true;
- int64_t Val = Memory.OffsetImm->getValue();
- return Val > -4096 && Val < 4096;
+ if (const auto *CE = dyn_cast<MCConstantExpr>(Memory.OffsetImm)) {
+ int64_t Val = CE->getValue();
+ return Val > -4096 && Val < 4096;
+ }
+ return false;
}
bool isAM2OffsetImm() const {
@@ -1608,11 +1617,14 @@ public:
if (Memory.OffsetRegNum) return true;
// Immediate offset in range [-255, 255].
if (!Memory.OffsetImm) return true;
- int64_t Val = Memory.OffsetImm->getValue();
- // The #-0 offset is encoded as std::numeric_limits<int32_t>::min(), and we
- // have to check for this too.
- return (Val > -256 && Val < 256) ||
- Val == std::numeric_limits<int32_t>::min();
+ if (const auto *CE = dyn_cast<MCConstantExpr>(Memory.OffsetImm)) {
+ int64_t Val = CE->getValue();
+ // The #-0 offset is encoded as std::numeric_limits<int32_t>::min(), and
+ // we have to check for this too.
+ return (Val > -256 && Val < 256) ||
+ Val == std::numeric_limits<int32_t>::min();
+ }
+ return false;
}
bool isAM3Offset() const {
@@ -1640,9 +1652,12 @@ public:
if (Memory.OffsetRegNum) return false;
// Immediate offset in range [-1020, 1020] and a multiple of 4.
if (!Memory.OffsetImm) return true;
- int64_t Val = Memory.OffsetImm->getValue();
- return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
- Val == std::numeric_limits<int32_t>::min();
+ if (const auto *CE = dyn_cast<MCConstantExpr>(Memory.OffsetImm)) {
+ int64_t Val = CE->getValue();
+ return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
+ Val == std::numeric_limits<int32_t>::min();
+ }
+ return false;
}
bool isAddrMode5FP16() const {
@@ -1656,9 +1671,12 @@ public:
if (Memory.OffsetRegNum) return false;
// Immediate offset in range [-510, 510] and a multiple of 2.
if (!Memory.OffsetImm) return true;
- int64_t Val = Memory.OffsetImm->getValue();
- return (Val >= -510 && Val <= 510 && ((Val & 1) == 0)) ||
- Val == std::numeric_limits<int32_t>::min();
+ if (const auto *CE = dyn_cast<MCConstantExpr>(Memory.OffsetImm)) {
+ int64_t Val = CE->getValue();
+ return (Val >= -510 && Val <= 510 && ((Val & 1) == 0)) ||
+ Val == std::numeric_limits<int32_t>::min();
+ }
+ return false;
}
bool isMemTBB() const {
@@ -1710,8 +1728,11 @@ public:
return false;
// Immediate offset, multiple of 4 in range [0, 124].
if (!Memory.OffsetImm) return true;
- int64_t Val = Memory.OffsetImm->getValue();
- return Val >= 0 && Val <= 124 && (Val % 4) == 0;
+ if (const auto *CE = dyn_cast<MCConstantExpr>(Memory.OffsetImm)) {
+ int64_t Val = CE->getValue();
+ return Val >= 0 && Val <= 124 && (Val % 4) == 0;
+ }
+ return false;
}
bool isMemThumbRIs2() const {
@@ -1720,8 +1741,11 @@ public:
return false;
// Immediate offset, multiple of 4 in range [0, 62].
if (!Memory.OffsetImm) return true;
- int64_t Val = Memory.OffsetImm->getValue();
- return Val >= 0 && Val <= 62 && (Val % 2) == 0;
+ if (const auto *CE = dyn_cast<MCConstantExpr>(Memory.OffsetImm)) {
+ int64_t Val = CE->getValue();
+ return Val >= 0 && Val <= 62 && (Val % 2) == 0;
+ }
+ return false;
}
bool isMemThumbRIs1() const {
@@ -1730,8 +1754,11 @@ public:
return false;
// Immediate offset in range [0, 31].
if (!Memory.OffsetImm) return true;
- int64_t Val = Memory.OffsetImm->getValue();
- return Val >= 0 && Val <= 31;
+ if (const auto *CE = dyn_cast<MCConstantExpr>(Memory.OffsetImm)) {
+ int64_t Val = CE->getValue();
+ return Val >= 0 && Val <= 31;
+ }
+ return false;
}
bool isMemThumbSPI() const {
@@ -1740,8 +1767,11 @@ public:
return false;
// Immediate offset, multiple of 4 in range [0, 1020].
if (!Memory.OffsetImm) return true;
- int64_t Val = Memory.OffsetImm->getValue();
- return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
+ if (const auto *CE = dyn_cast<MCConstantExpr>(Memory.OffsetImm)) {
+ int64_t Val = CE->getValue();
+ return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
+ }
+ return false;
}
bool isMemImm8s4Offset() const {
@@ -1754,11 +1784,15 @@ public:
return false;
// Immediate offset a multiple of 4 in range [-1020, 1020].
if (!Memory.OffsetImm) return true;
- int64_t Val = Memory.OffsetImm->getValue();
- // Special case, #-0 is std::numeric_limits<int32_t>::min().
- return (Val >= -1020 && Val <= 1020 && (Val & 3) == 0) ||
- Val == std::numeric_limits<int32_t>::min();
+ if (const auto *CE = dyn_cast<MCConstantExpr>(Memory.OffsetImm)) {
+ int64_t Val = CE->getValue();
+ // Special case, #-0 is std::numeric_limits<int32_t>::min().
+ return (Val >= -1020 && Val <= 1020 && (Val & 3) == 0) ||
+ Val == std::numeric_limits<int32_t>::min();
+ }
+ return false;
}
+
bool isMemImm7s4Offset() const {
// If we have an immediate that's not a constant, treat it as a label
// reference needing a fixup. If it is a constant, it's something else
@@ -1771,17 +1805,24 @@ public:
return false;
// Immediate offset a multiple of 4 in range [-508, 508].
if (!Memory.OffsetImm) return true;
- int64_t Val = Memory.OffsetImm->getValue();
- // Special case, #-0 is INT32_MIN.
- return (Val >= -508 && Val <= 508 && (Val & 3) == 0) || Val == INT32_MIN;
+ if (const auto *CE = dyn_cast<MCConstantExpr>(Memory.OffsetImm)) {
+ int64_t Val = CE->getValue();
+ // Special case, #-0 is INT32_MIN.
+ return (Val >= -508 && Val <= 508 && (Val & 3) == 0) || Val == INT32_MIN;
+ }
+ return false;
}
+
bool isMemImm0_1020s4Offset() const {
if (!isGPRMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
return false;
// Immediate offset a multiple of 4 in range [0, 1020].
if (!Memory.OffsetImm) return true;
- int64_t Val = Memory.OffsetImm->getValue();
- return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
+ if (const auto *CE = dyn_cast<MCConstantExpr>(Memory.OffsetImm)) {
+ int64_t Val = CE->getValue();
+ return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
+ }
+ return false;
}
bool isMemImm8Offset() const {
@@ -1791,9 +1832,12 @@ public:
if (Memory.BaseRegNum == ARM::PC) return false;
// Immediate offset in range [-255, 255].
if (!Memory.OffsetImm) return true;
- int64_t Val = Memory.OffsetImm->getValue();
- return (Val == std::numeric_limits<int32_t>::min()) ||
- (Val > -256 && Val < 256);
+ if (const auto *CE = dyn_cast<MCConstantExpr>(Memory.OffsetImm)) {
+ int64_t Val = CE->getValue();
+ return (Val == std::numeric_limits<int32_t>::min()) ||
+ (Val > -256 && Val < 256);
+ }
+ return false;
}
template<unsigned Bits, unsigned RegClassID>
@@ -1806,22 +1850,25 @@ public:
// [-127, 127], shifted left by Bits.
if (!Memory.OffsetImm) return true;
- int64_t Val = Memory.OffsetImm->getValue();
+ if (const auto *CE = dyn_cast<MCConstantExpr>(Memory.OffsetImm)) {
+ int64_t Val = CE->getValue();
- // INT32_MIN is a special-case value (indicating the encoding with
- // zero offset and the subtract bit set)
- if (Val == INT32_MIN)
- return true;
+ // INT32_MIN is a special-case value (indicating the encoding with
+ // zero offset and the subtract bit set)
+ if (Val == INT32_MIN)
+ return true;
- unsigned Divisor = 1U << Bits;
+ unsigned Divisor = 1U << Bits;
- // Check that the low bits are zero
- if (Val % Divisor != 0)
- return false;
+ // Check that the low bits are zero
+ if (Val % Divisor != 0)
+ return false;
- // Check that the remaining offset is within range.
- Val /= Divisor;
- return (Val >= -127 && Val <= 127);
+ // Check that the remaining offset is within range.
+ Val /= Divisor;
+ return (Val >= -127 && Val <= 127);
+ }
+ return false;
}
template <int shift> bool isMemRegRQOffset() const {
@@ -1853,20 +1900,24 @@ public:
Memory.BaseRegNum))
return false;
- if(!Memory.OffsetImm) return true;
+ if (!Memory.OffsetImm)
+ return true;
static_assert(shift < 56,
"Such that we dont shift by a value higher than 62");
- int64_t Val = Memory.OffsetImm->getValue();
+ if (const auto *CE = dyn_cast<MCConstantExpr>(Memory.OffsetImm)) {
+ int64_t Val = CE->getValue();
- // The value must be a multiple of (1 << shift)
- if ((Val & ((1U << shift) - 1)) != 0)
- return false;
+ // The value must be a multiple of (1 << shift)
+ if ((Val & ((1U << shift) - 1)) != 0)
+ return false;
- // And be in the right range, depending on the amount that it is shifted
- // by. Shift 0, is equal to 7 unsigned bits, the sign bit is set
- // separately.
- int64_t Range = (1U << (7+shift)) - 1;
- return (Val == INT32_MIN) || (Val > -Range && Val < Range);
+ // And be in the right range, depending on the amount that it is shifted
+ // by. Shift 0, is equal to 7 unsigned bits, the sign bit is set
+ // separately.
+ int64_t Range = (1U << (7 + shift)) - 1;
+ return (Val == INT32_MIN) || (Val > -Range && Val < Range);
+ }
+ return false;
}
bool isMemPosImm8Offset() const {
@@ -1874,8 +1925,11 @@ public:
return false;
// Immediate offset in range [0, 255].
if (!Memory.OffsetImm) return true;
- int64_t Val = Memory.OffsetImm->getValue();
- return Val >= 0 && Val < 256;
+ if (const auto *CE = dyn_cast<MCConstantExpr>(Memory.OffsetImm)) {
+ int64_t Val = CE->getValue();
+ return Val >= 0 && Val < 256;
+ }
+ return false;
}
bool isMemNegImm8Offset() const {
@@ -1885,9 +1939,12 @@ public:
if (Memory.BaseRegNum == ARM::PC) return false;
// Immediate offset in range [-255, -1].
if (!Memory.OffsetImm) return false;
- int64_t Val = Memory.OffsetImm->getValue();
- return (Val == std::numeric_limits<int32_t>::min()) ||
- (Val > -256 && Val < 0);
+ if (const auto *CE = dyn_cast<MCConstantExpr>(Memory.OffsetImm)) {
+ int64_t Val = CE->getValue();
+ return (Val == std::numeric_limits<int32_t>::min()) ||
+ (Val > -256 && Val < 0);
+ }
+ return false;
}
bool isMemUImm12Offset() const {
@@ -1895,8 +1952,11 @@ public:
return false;
// Immediate offset in range [0, 4095].
if (!Memory.OffsetImm) return true;
- int64_t Val = Memory.OffsetImm->getValue();
- return (Val >= 0 && Val < 4096);
+ if (const auto *CE = dyn_cast<MCConstantExpr>(Memory.OffsetImm)) {
+ int64_t Val = CE->getValue();
+ return (Val >= 0 && Val < 4096);
+ }
+ return false;
}
bool isMemImm12Offset() const {
@@ -1911,9 +1971,14 @@ public:
return false;
// Immediate offset in range [-4095, 4095].
if (!Memory.OffsetImm) return true;
- int64_t Val = Memory.OffsetImm->getValue();
- return (Val > -4096 && Val < 4096) ||
- (Val == std::numeric_limits<int32_t>::min());
+ if (const auto *CE = dyn_cast<MCConstantExpr>(Memory.OffsetImm)) {
+ int64_t Val = CE->getValue();
+ return (Val > -4096 && Val < 4096) ||
+ (Val == std::numeric_limits<int32_t>::min());
+ }
+ // If we have an immediate that's not a constant, treat it as a
+ // symbolic expression needing a fixup.
+ return true;
}
bool isConstPoolAsmImm() const {
@@ -2760,7 +2825,10 @@ public:
assert(isGPRMem() && "Unknown value type!");
assert(isa<MCConstantExpr>(Memory.OffsetImm) && "Unknown value type!");
- Inst.addOperand(MCOperand::createImm(Memory.OffsetImm->getValue()));
+ if (const auto *CE = dyn_cast<MCConstantExpr>(Memory.OffsetImm))
+ Inst.addOperand(MCOperand::createImm(CE->getValue()));
+ else
+ Inst.addOperand(MCOperand::createExpr(Memory.OffsetImm));
}
void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
@@ -2800,8 +2868,10 @@ public:
void addMemPCRelImm12Operands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
- int32_t Imm = Memory.OffsetImm->getValue();
- Inst.addOperand(MCOperand::createImm(Imm));
+ if (const auto *CE = dyn_cast<MCConstantExpr>(Memory.OffsetImm))
+ Inst.addOperand(MCOperand::createImm(CE->getValue()));
+ else
+ Inst.addOperand(MCOperand::createExpr(Memory.OffsetImm));
}
void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
@@ -2872,22 +2942,31 @@ public:
void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
assert(N == 3 && "Invalid number of operands!");
- int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
+ Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
+ Inst.addOperand(MCOperand::createReg(Memory.OffsetRegNum));
if (!Memory.OffsetRegNum) {
- ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
- // Special case for #-0
- if (Val == std::numeric_limits<int32_t>::min()) Val = 0;
- if (Val < 0) Val = -Val;
- Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
+ if (!Memory.OffsetImm)
+ Inst.addOperand(MCOperand::createImm(0));
+ else if (const auto *CE = dyn_cast<MCConstantExpr>(Memory.OffsetImm)) {
+ int32_t Val = CE->getValue();
+ ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
+ // Special case for #-0
+ if (Val == std::numeric_limits<int32_t>::min())
+ Val = 0;
+ if (Val < 0)
+ Val = -Val;
+ Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
+ Inst.addOperand(MCOperand::createImm(Val));
+ } else
+ Inst.addOperand(MCOperand::createExpr(Memory.OffsetImm));
} else {
// For register offset, we encode the shift type and negation flag
// here.
- Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
- Memory.ShiftImm, Memory.ShiftType);
+ int32_t Val =
+ ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
+ Memory.ShiftImm, Memory.ShiftType);
+ Inst.addOperand(MCOperand::createImm(Val));
}
- Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
- Inst.addOperand(MCOperand::createReg(Memory.OffsetRegNum));
- Inst.addOperand(MCOperand::createImm(Val));
}
void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
@@ -2916,21 +2995,30 @@ public:
return;
}
- int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
+ Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
+ Inst.addOperand(MCOperand::createReg(Memory.OffsetRegNum));
if (!Memory.OffsetRegNum) {
- ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
- // Special case for #-0
- if (Val == std::numeric_limits<int32_t>::min()) Val = 0;
- if (Val < 0) Val = -Val;
- Val = ARM_AM::getAM3Opc(AddSub, Val);
+ if (!Memory.OffsetImm)
+ Inst.addOperand(MCOperand::createImm(0));
+ else if (const auto *CE = dyn_cast<MCConstantExpr>(Memory.OffsetImm)) {
+ int32_t Val = CE->getValue();
+ ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
+ // Special case for #-0
+ if (Val == std::numeric_limits<int32_t>::min())
+ Val = 0;
+ if (Val < 0)
+ Val = -Val;
+ Val = ARM_AM::getAM3Opc(AddSub, Val);
+ Inst.addOperand(MCOperand::createImm(Val));
+ } else
+ Inst.addOperand(MCOperand::createExpr(Memory.OffsetImm));
} else {
// For register offset, we encode the shift type and negation flag
// here.
- Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
+ int32_t Val =
+ ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
+ Inst.addOperand(MCOperand::createImm(Val));
}
- Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
- Inst.addOperand(MCOperand::createReg(Memory.OffsetRegNum));
- Inst.addOperand(MCOperand::createImm(Val));
}
void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
@@ -2966,15 +3054,22 @@ public:
return;
}
- // The lower two bits are always zero and as such are not encoded.
- int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
- ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
- // Special case for #-0
- if (Val == std::numeric_limits<int32_t>::min()) Val = 0;
- if (Val < 0) Val = -Val;
- Val = ARM_AM::getAM5Opc(AddSub, Val);
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
- Inst.addOperand(MCOperand::createImm(Val));
+ if (!Memory.OffsetImm)
+ Inst.addOperand(MCOperand::createImm(0));
+ else if (const auto *CE = dyn_cast<MCConstantExpr>(Memory.OffsetImm)) {
+ // The lower two bits are always zero and as such are not encoded.
+ int32_t Val = CE->getValue() / 4;
+ ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
+ // Special case for #-0
+ if (Val == std::numeric_limits<int32_t>::min())
+ Val = 0;
+ if (Val < 0)
+ Val = -Val;
+ Val = ARM_AM::getAM5Opc(AddSub, Val);
+ Inst.addOperand(MCOperand::createImm(Val));
+ } else
+ Inst.addOperand(MCOperand::createExpr(Memory.OffsetImm));
}
void addAddrMode5FP16Operands(MCInst &Inst, unsigned N) const {
@@ -2988,15 +3083,22 @@ public:
return;
}
- // The lower bit is always zero and as such is not encoded.
- int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 2 : 0;
- ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
- // Special case for #-0
- if (Val == std::numeric_limits<int32_t>::min()) Val = 0;
- if (Val < 0) Val = -Val;
- Val = ARM_AM::getAM5FP16Opc(AddSub, Val);
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
- Inst.addOperand(MCOperand::createImm(Val));
+ // The lower bit is always zero and as such is not encoded.
+ if (!Memory.OffsetImm)
+ Inst.addOperand(MCOperand::createImm(0));
+ else if (const auto *CE = dyn_cast<MCConstantExpr>(Memory.OffsetImm)) {
+ int32_t Val = CE->getValue() / 2;
+ ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
+ // Special case for #-0
+ if (Val == std::numeric_limits<int32_t>::min())
+ Val = 0;
+ if (Val < 0)
+ Val = -Val;
+ Val = ARM_AM::getAM5FP16Opc(AddSub, Val);
+ Inst.addOperand(MCOperand::createImm(Val));
+ } else
+ Inst.addOperand(MCOperand::createExpr(Memory.OffsetImm));
}
void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
@@ -3010,9 +3112,8 @@ public:
return;
}
- int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
- Inst.addOperand(MCOperand::createImm(Val));
+ addExpr(Inst, Memory.OffsetImm);
}
void addMemImm7s4OffsetOperands(MCInst &Inst, unsigned N) const {
@@ -3026,24 +3127,26 @@ public:
return;
}
- int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
- Inst.addOperand(MCOperand::createImm(Val));
+ addExpr(Inst, Memory.OffsetImm);
}
void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
assert(N == 2 && "Invalid number of operands!");
- // The lower two bits are always zero and as such are not encoded.
- int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
- Inst.addOperand(MCOperand::createImm(Val));
+ if (!Memory.OffsetImm)
+ Inst.addOperand(MCOperand::createImm(0));
+ else if (const auto *CE = dyn_cast<MCConstantExpr>(Memory.OffsetImm))
+ // The lower two bits are always zero and as such are not encoded.
+ Inst.addOperand(MCOperand::createImm(CE->getValue() / 4));
+ else
+ Inst.addOperand(MCOperand::createExpr(Memory.OffsetImm));
}
void addMemImmOffsetOperands(MCInst &Inst, unsigned N) const {
assert(N == 2 && "Invalid number of operands!");
- int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
- Inst.addOperand(MCOperand::createImm(Val));
+ addExpr(Inst, Memory.OffsetImm);
}
void addMemRegRQOffsetOperands(MCInst &Inst, unsigned N) const {
@@ -3062,9 +3165,8 @@ public:
}
// Otherwise, it's a normal memory reg+offset.
- int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
- Inst.addOperand(MCOperand::createImm(Val));
+ addExpr(Inst, Memory.OffsetImm);
}
void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
@@ -3077,9 +3179,8 @@ public:
}
// Otherwise, it's a normal memory reg+offset.
- int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
- Inst.addOperand(MCOperand::createImm(Val));
+ addExpr(Inst, Memory.OffsetImm);
}
void addConstPoolAsmImmOperands(MCInst &Inst, unsigned N) const {
@@ -3126,30 +3227,43 @@ public:
void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
assert(N == 2 && "Invalid number of operands!");
- int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
- Inst.addOperand(MCOperand::createImm(Val));
+ if (!Memory.OffsetImm)
+ Inst.addOperand(MCOperand::createImm(0));
+ else if (const auto *CE = dyn_cast<MCConstantExpr>(Memory.OffsetImm))
+ // The lower two bits are always zero and as such are not encoded.
+ Inst.addOperand(MCOperand::createImm(CE->getValue() / 4));
+ else
+ Inst.addOperand(MCOperand::createExpr(Memory.OffsetImm));
}
void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
assert(N == 2 && "Invalid number of operands!");
- int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
- Inst.addOperand(MCOperand::createImm(Val));
+ if (!Memory.OffsetImm)
+ Inst.addOperand(MCOperand::createImm(0));
+ else if (const auto *CE = dyn_cast<MCConstantExpr>(Memory.OffsetImm))
+ Inst.addOperand(MCOperand::createImm(CE->getValue() / 2));
+ else
+ Inst.addOperand(MCOperand::createExpr(Memory.OffsetImm));
}
void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
assert(N == 2 && "Invalid number of operands!");
- int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
- Inst.addOperand(MCOperand::createImm(Val));
+ addExpr(Inst, Memory.OffsetImm);
}
void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
assert(N == 2 && "Invalid number of operands!");
- int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
- Inst.addOperand(MCOperand::createImm(Val));
+ if (!Memory.OffsetImm)
+ Inst.addOperand(MCOperand::createImm(0));
+ else if (const auto *CE = dyn_cast<MCConstantExpr>(Memory.OffsetImm))
+ // The lower two bits are always zero and as such are not encoded.
+ Inst.addOperand(MCOperand::createImm(CE->getValue() / 4));
+ else
+ Inst.addOperand(MCOperand::createExpr(Memory.OffsetImm));
}
void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
@@ -3686,10 +3800,9 @@ public:
}
static std::unique_ptr<ARMOperand>
- CreateMem(unsigned BaseRegNum, const MCConstantExpr *OffsetImm,
- unsigned OffsetRegNum, ARM_AM::ShiftOpc ShiftType,
- unsigned ShiftImm, unsigned Alignment, bool isNegative, SMLoc S,
- SMLoc E, SMLoc AlignmentLoc = SMLoc()) {
+ CreateMem(unsigned BaseRegNum, const MCExpr *OffsetImm, unsigned OffsetRegNum,
+ ARM_AM::ShiftOpc ShiftType, unsigned ShiftImm, unsigned Alignment,
+ bool isNegative, SMLoc S, SMLoc E, SMLoc AlignmentLoc = SMLoc()) {
auto Op = std::make_unique<ARMOperand>(k_Memory);
Op->Memory.BaseRegNum = BaseRegNum;
Op->Memory.OffsetImm = OffsetImm;
@@ -4899,7 +5012,7 @@ ARMAsmParser::parseTraceSyncBarrierOptOperand(OperandVector &Operands) {
if (Tok.isNot(AsmToken::Identifier))
return MatchOperand_NoMatch;
- if (!Tok.getString().equals_lower("csync"))
+ if (!Tok.getString().equals_insensitive("csync"))
return MatchOperand_NoMatch;
Parser.Lex(); // Eat identifier token.
@@ -4919,7 +5032,7 @@ ARMAsmParser::parseInstSyncBarrierOptOperand(OperandVector &Operands) {
if (Tok.is(AsmToken::Identifier)) {
StringRef OptStr = Tok.getString();
- if (OptStr.equals_lower("sy"))
+ if (OptStr.equals_insensitive("sy"))
Opt = ARM_ISB::SY;
else
return MatchOperand_NoMatch;
@@ -5818,23 +5931,24 @@ bool ARMAsmParser::parseMemory(OperandVector &Operands) {
E = Parser.getTok().getLoc();
bool isNegative = getParser().getTok().is(AsmToken::Minus);
- const MCExpr *Offset;
+ const MCExpr *Offset, *AdjustedOffset;
if (getParser().parseExpression(Offset))
return true;
- // The expression has to be a constant. Memory references with relocations
- // don't come through here, as they use the <label> forms of the relevant
- // instructions.
- const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
- if (!CE)
- return Error (E, "constant expression expected");
-
- // If the constant was #-0, represent it as
- // std::numeric_limits<int32_t>::min().
- int32_t Val = CE->getValue();
- if (isNegative && Val == 0)
- CE = MCConstantExpr::create(std::numeric_limits<int32_t>::min(),
- getContext());
+ if (const auto *CE = dyn_cast<MCConstantExpr>(Offset)) {
+ // If the constant was #-0, represent it as
+ // std::numeric_limits<int32_t>::min().
+ int32_t Val = CE->getValue();
+ if (isNegative && Val == 0)
+ CE = MCConstantExpr::create(std::numeric_limits<int32_t>::min(),
+ getContext());
+ // Don't worry about range checking the value here. That's handled by
+ // the is*() predicates.
+ AdjustedOffset = CE;
+ } else
+ AdjustedOffset = Offset;
+ Operands.push_back(ARMOperand::CreateMem(
+ BaseRegNum, AdjustedOffset, 0, ARM_AM::no_shift, 0, 0, false, S, E));
// Now we should have the closing ']'
if (Parser.getTok().isNot(AsmToken::RBrac))
@@ -5842,12 +5956,6 @@ bool ARMAsmParser::parseMemory(OperandVector &Operands) {
E = Parser.getTok().getEndLoc();
Parser.Lex(); // Eat right bracket token.
- // Don't worry about range checking the value here. That's handled by
- // the is*() predicates.
- Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
- ARM_AM::no_shift, 0, 0,
- false, S, E));
-
// If there's a pre-indexing writeback marker, '!', just add it as a token
// operand.
if (Parser.getTok().is(AsmToken::Exclaim)) {
@@ -6086,7 +6194,7 @@ bool ARMAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
return true;
// If this is VMRS, check for the apsr_nzcv operand.
if (Mnemonic == "vmrs" &&
- Parser.getTok().getString().equals_lower("apsr_nzcv")) {
+ Parser.getTok().getString().equals_insensitive("apsr_nzcv")) {
S = Parser.getTok().getLoc();
Parser.Lex();
Operands.push_back(ARMOperand::CreateToken("APSR_nzcv", S));
@@ -6222,10 +6330,10 @@ bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
}
enum {
- COFF = (1 << MCObjectFileInfo::IsCOFF),
- ELF = (1 << MCObjectFileInfo::IsELF),
- MACHO = (1 << MCObjectFileInfo::IsMachO),
- WASM = (1 << MCObjectFileInfo::IsWasm),
+ COFF = (1 << MCContext::IsCOFF),
+ ELF = (1 << MCContext::IsELF),
+ MACHO = (1 << MCContext::IsMachO),
+ WASM = (1 << MCContext::IsWasm),
};
static const struct PrefixEntry {
const char *Spelling;
@@ -6248,20 +6356,21 @@ bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
}
uint8_t CurrentFormat;
- switch (getContext().getObjectFileInfo()->getObjectFileType()) {
- case MCObjectFileInfo::IsMachO:
+ switch (getContext().getObjectFileType()) {
+ case MCContext::IsMachO:
CurrentFormat = MACHO;
break;
- case MCObjectFileInfo::IsELF:
+ case MCContext::IsELF:
CurrentFormat = ELF;
break;
- case MCObjectFileInfo::IsCOFF:
+ case MCContext::IsCOFF:
CurrentFormat = COFF;
break;
- case MCObjectFileInfo::IsWasm:
+ case MCContext::IsWasm:
CurrentFormat = WASM;
break;
- case MCObjectFileInfo::IsXCOFF:
+ case MCContext::IsGOFF:
+ case MCContext::IsXCOFF:
llvm_unreachable("unexpected object format");
break;
}
@@ -7658,6 +7767,33 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst,
"source register and base register can't be identical");
return false;
}
+ case ARM::t2LDR_PRE_imm:
+ case ARM::t2LDR_POST_imm:
+ case ARM::t2STR_PRE_imm:
+ case ARM::t2STR_POST_imm: {
+ // Rt must be different from Rn.
+ const unsigned Rt = MRI->getEncodingValue(Inst.getOperand(0).getReg());
+ const unsigned Rn = MRI->getEncodingValue(Inst.getOperand(1).getReg());
+
+ if (Rt == Rn)
+ return Error(Operands[3]->getStartLoc(),
+ "destination register and base register can't be identical");
+ if (Inst.getOpcode() == ARM::t2LDR_POST_imm ||
+ Inst.getOpcode() == ARM::t2STR_POST_imm) {
+ int Imm = Inst.getOperand(2).getImm();
+ if (Imm > 255 || Imm < -255)
+ return Error(Operands[5]->getStartLoc(),
+ "operand must be in range [-255, 255]");
+ }
+ if (Inst.getOpcode() == ARM::t2STR_PRE_imm ||
+ Inst.getOpcode() == ARM::t2STR_POST_imm) {
+ if (Inst.getOperand(0).getReg() == ARM::PC) {
+ return Error(Operands[3]->getStartLoc(),
+ "operand must be a register in range [r0, r14]");
+ }
+ }
+ return false;
+ }
case ARM::LDR_PRE_IMM:
case ARM::LDR_PRE_REG:
case ARM::t2LDR_PRE:
@@ -7923,7 +8059,10 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst,
break;
case ARM::t2B: {
int op = (Operands[2]->isImm()) ? 2 : 3;
- if (!static_cast<ARMOperand &>(*Operands[op]).isSignedOffset<24, 1>())
+ ARMOperand &Operand = static_cast<ARMOperand &>(*Operands[op]);
+ // Delay the checks of symbolic expressions until they are resolved.
+ if (!isa<MCBinaryExpr>(Operand.getImm()) &&
+ !Operand.isSignedOffset<24, 1>())
return Error(Operands[op]->getStartLoc(), "branch target out of range");
break;
}
@@ -8625,6 +8764,34 @@ bool ARMAsmParser::processInstruction(MCInst &Inst,
Inst = TmpInst;
return true;
}
+ // Aliases for imm syntax of LDR instructions.
+ case ARM::t2LDR_PRE_imm:
+ case ARM::t2LDR_POST_imm: {
+ MCInst TmpInst;
+ TmpInst.setOpcode(Inst.getOpcode() == ARM::t2LDR_PRE_imm ? ARM::t2LDR_PRE
+ : ARM::t2LDR_POST);
+ TmpInst.addOperand(Inst.getOperand(0)); // Rt
+ TmpInst.addOperand(Inst.getOperand(4)); // Rt_wb
+ TmpInst.addOperand(Inst.getOperand(1)); // Rn
+ TmpInst.addOperand(Inst.getOperand(2)); // imm
+ TmpInst.addOperand(Inst.getOperand(3)); // CondCode
+ Inst = TmpInst;
+ return true;
+ }
+ // Aliases for imm syntax of STR instructions.
+ case ARM::t2STR_PRE_imm:
+ case ARM::t2STR_POST_imm: {
+ MCInst TmpInst;
+ TmpInst.setOpcode(Inst.getOpcode() == ARM::t2STR_PRE_imm ? ARM::t2STR_PRE
+ : ARM::t2STR_POST);
+ TmpInst.addOperand(Inst.getOperand(4)); // Rt_wb
+ TmpInst.addOperand(Inst.getOperand(0)); // Rt
+ TmpInst.addOperand(Inst.getOperand(1)); // Rn
+ TmpInst.addOperand(Inst.getOperand(2)); // imm
+ TmpInst.addOperand(Inst.getOperand(3)); // CondCode
+ Inst = TmpInst;
+ return true;
+ }
// Aliases for alternate PC+imm syntax of LDR instructions.
case ARM::t2LDRpcrel:
// Select the narrow version if the immediate will fit.
@@ -10835,10 +11002,9 @@ bool ARMAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
/// parseDirective parses the arm specific directives
bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
- const MCObjectFileInfo::Environment Format =
- getContext().getObjectFileInfo()->getObjectFileType();
- bool IsMachO = Format == MCObjectFileInfo::IsMachO;
- bool IsCOFF = Format == MCObjectFileInfo::IsCOFF;
+ const MCContext::Environment Format = getContext().getObjectFileType();
+ bool IsMachO = Format == MCContext::IsMachO;
+ bool IsCOFF = Format == MCContext::IsCOFF;
std::string IDVal = DirectiveID.getIdentifier().lower();
if (IDVal == ".word")
@@ -10976,8 +11142,8 @@ void ARMAsmParser::onLabelParsed(MCSymbol *Symbol) {
/// ::= .thumbfunc symbol_name
bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
MCAsmParser &Parser = getParser();
- const auto Format = getContext().getObjectFileInfo()->getObjectFileType();
- bool IsMachO = Format == MCObjectFileInfo::IsMachO;
+ const auto Format = getContext().getObjectFileType();
+ bool IsMachO = Format == MCContext::IsMachO;
// Darwin asm has (optionally) function name after .thumb_func direction
// ELF doesn't
@@ -11000,6 +11166,12 @@ bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
"unexpected token in '.thumb_func' directive"))
return true;
+ // .thumb_func implies .thumb
+ if (!isThumb())
+ SwitchMode();
+
+ getParser().getStreamer().emitAssemblerFlag(MCAF_Code16);
+
NextSymbolIsThumb = true;
return false;
}
@@ -11154,8 +11326,8 @@ bool ARMAsmParser::parseDirectiveEabiAttr(SMLoc L) {
TagLoc = Parser.getTok().getLoc();
if (Parser.getTok().is(AsmToken::Identifier)) {
StringRef Name = Parser.getTok().getIdentifier();
- Optional<unsigned> Ret =
- ELFAttrs::attrTypeFromString(Name, ARMBuildAttrs::ARMAttributeTags);
+ Optional<unsigned> Ret = ELFAttrs::attrTypeFromString(
+ Name, ARMBuildAttrs::getARMAttributeTags());
if (!Ret.hasValue()) {
Error(TagLoc, "attribute name not recognised: " + Name);
return false;
@@ -12060,9 +12232,7 @@ void ARMAsmParser::ReportNearMisses(SmallVectorImpl<NearMissInfo> &NearMisses,
}
}
-/// parseDirectiveArchExtension
-/// ::= .arch_extension [no]feature
-bool ARMAsmParser::parseDirectiveArchExtension(SMLoc L) {
+bool ARMAsmParser::enableArchExtFeature(StringRef Name, SMLoc &ExtLoc) {
// FIXME: This structure should be moved inside ARMTargetParser
// when we start to table-generate them, and we can use the ARM
// flags below, that were generated by table-gen.
@@ -12071,48 +12241,45 @@ bool ARMAsmParser::parseDirectiveArchExtension(SMLoc L) {
const FeatureBitset ArchCheck;
const FeatureBitset Features;
} Extensions[] = {
- { ARM::AEK_CRC, {Feature_HasV8Bit}, {ARM::FeatureCRC} },
- { ARM::AEK_CRYPTO, {Feature_HasV8Bit},
- {ARM::FeatureCrypto, ARM::FeatureNEON, ARM::FeatureFPARMv8} },
- { ARM::AEK_FP, {Feature_HasV8Bit},
- {ARM::FeatureVFP2_SP, ARM::FeatureFPARMv8} },
- { (ARM::AEK_HWDIVTHUMB | ARM::AEK_HWDIVARM),
- {Feature_HasV7Bit, Feature_IsNotMClassBit},
- {ARM::FeatureHWDivThumb, ARM::FeatureHWDivARM} },
- { ARM::AEK_MP, {Feature_HasV7Bit, Feature_IsNotMClassBit},
- {ARM::FeatureMP} },
- { ARM::AEK_SIMD, {Feature_HasV8Bit},
- {ARM::FeatureNEON, ARM::FeatureVFP2_SP, ARM::FeatureFPARMv8} },
- { ARM::AEK_SEC, {Feature_HasV6KBit}, {ARM::FeatureTrustZone} },
- // FIXME: Only available in A-class, isel not predicated
- { ARM::AEK_VIRT, {Feature_HasV7Bit}, {ARM::FeatureVirtualization} },
- { ARM::AEK_FP16, {Feature_HasV8_2aBit},
- {ARM::FeatureFPARMv8, ARM::FeatureFullFP16} },
- { ARM::AEK_RAS, {Feature_HasV8Bit}, {ARM::FeatureRAS} },
- { ARM::AEK_LOB, {Feature_HasV8_1MMainlineBit}, {ARM::FeatureLOB} },
- // FIXME: Unsupported extensions.
- { ARM::AEK_OS, {}, {} },
- { ARM::AEK_IWMMXT, {}, {} },
- { ARM::AEK_IWMMXT2, {}, {} },
- { ARM::AEK_MAVERICK, {}, {} },
- { ARM::AEK_XSCALE, {}, {} },
+ {ARM::AEK_CRC, {Feature_HasV8Bit}, {ARM::FeatureCRC}},
+ {ARM::AEK_AES,
+ {Feature_HasV8Bit},
+ {ARM::FeatureAES, ARM::FeatureNEON, ARM::FeatureFPARMv8}},
+ {ARM::AEK_SHA2,
+ {Feature_HasV8Bit},
+ {ARM::FeatureSHA2, ARM::FeatureNEON, ARM::FeatureFPARMv8}},
+ {ARM::AEK_CRYPTO,
+ {Feature_HasV8Bit},
+ {ARM::FeatureCrypto, ARM::FeatureNEON, ARM::FeatureFPARMv8}},
+ {ARM::AEK_FP,
+ {Feature_HasV8Bit},
+ {ARM::FeatureVFP2_SP, ARM::FeatureFPARMv8}},
+ {(ARM::AEK_HWDIVTHUMB | ARM::AEK_HWDIVARM),
+ {Feature_HasV7Bit, Feature_IsNotMClassBit},
+ {ARM::FeatureHWDivThumb, ARM::FeatureHWDivARM}},
+ {ARM::AEK_MP,
+ {Feature_HasV7Bit, Feature_IsNotMClassBit},
+ {ARM::FeatureMP}},
+ {ARM::AEK_SIMD,
+ {Feature_HasV8Bit},
+ {ARM::FeatureNEON, ARM::FeatureVFP2_SP, ARM::FeatureFPARMv8}},
+ {ARM::AEK_SEC, {Feature_HasV6KBit}, {ARM::FeatureTrustZone}},
+ // FIXME: Only available in A-class, isel not predicated
+ {ARM::AEK_VIRT, {Feature_HasV7Bit}, {ARM::FeatureVirtualization}},
+ {ARM::AEK_FP16,
+ {Feature_HasV8_2aBit},
+ {ARM::FeatureFPARMv8, ARM::FeatureFullFP16}},
+ {ARM::AEK_RAS, {Feature_HasV8Bit}, {ARM::FeatureRAS}},
+ {ARM::AEK_LOB, {Feature_HasV8_1MMainlineBit}, {ARM::FeatureLOB}},
+ // FIXME: Unsupported extensions.
+ {ARM::AEK_OS, {}, {}},
+ {ARM::AEK_IWMMXT, {}, {}},
+ {ARM::AEK_IWMMXT2, {}, {}},
+ {ARM::AEK_MAVERICK, {}, {}},
+ {ARM::AEK_XSCALE, {}, {}},
};
-
- MCAsmParser &Parser = getParser();
-
- if (getLexer().isNot(AsmToken::Identifier))
- return Error(getLexer().getLoc(), "expected architecture extension name");
-
- StringRef Name = Parser.getTok().getString();
- SMLoc ExtLoc = Parser.getTok().getLoc();
- Lex();
-
- if (parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.arch_extension' directive"))
- return true;
-
bool EnableFeature = true;
- if (Name.startswith_lower("no")) {
+ if (Name.startswith_insensitive("no")) {
EnableFeature = false;
Name = Name.substr(2);
}
@@ -12140,9 +12307,36 @@ bool ARMAsmParser::parseDirectiveArchExtension(SMLoc L) {
}
FeatureBitset Features = ComputeAvailableFeatures(STI.getFeatureBits());
setAvailableFeatures(Features);
- return false;
+ return true;
+ }
+ return false;
+}
+
+/// parseDirectiveArchExtension
+/// ::= .arch_extension [no]feature
+bool ARMAsmParser::parseDirectiveArchExtension(SMLoc L) {
+
+ MCAsmParser &Parser = getParser();
+
+ if (getLexer().isNot(AsmToken::Identifier))
+ return Error(getLexer().getLoc(), "expected architecture extension name");
+
+ StringRef Name = Parser.getTok().getString();
+ SMLoc ExtLoc = Parser.getTok().getLoc();
+ Lex();
+
+ if (parseToken(AsmToken::EndOfStatement,
+ "unexpected token in '.arch_extension' directive"))
+ return true;
+
+ if (Name == "nocrypto") {
+ enableArchExtFeature("nosha2", ExtLoc);
+ enableArchExtFeature("noaes", ExtLoc);
}
+ if (enableArchExtFeature(Name, ExtLoc))
+ return false;
+
return Error(ExtLoc, "unknown architectural extension: " + Name);
}