summaryrefslogtreecommitdiff
path: root/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/Mips/AsmParser/MipsAsmParser.cpp')
-rw-r--r--lib/Target/Mips/AsmParser/MipsAsmParser.cpp814
1 files changed, 533 insertions, 281 deletions
diff --git a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
index 345b081500a4..2acf701b43cb 100644
--- a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
+++ b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
@@ -146,10 +146,15 @@ class MipsAsmParser : public MCTargetAsmParser {
/// If true, then CpSaveLocation is a register, otherwise it's an offset.
bool CpSaveLocationIsRegister;
+ // Map of register aliases created via the .set directive.
+ StringMap<AsmToken> RegisterSets;
+
// Print a warning along with its fix-it message at the given range.
void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
SMRange Range, bool ShowColors = true);
+ void ConvertXWPOperands(MCInst &Inst, const OperandVector &Operands);
+
#define GET_ASSEMBLER_HEADER
#include "MipsGenAsmMatcher.inc"
@@ -182,12 +187,14 @@ class MipsAsmParser : public MCTargetAsmParser {
matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
StringRef Identifier, SMLoc S);
OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands,
+ const AsmToken &Token,
+ SMLoc S);
+ OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands,
SMLoc S);
OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
OperandMatchResultTy parseImm(OperandVector &Operands);
OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
OperandMatchResultTy parseInvNum(OperandVector &Operands);
- OperandMatchResultTy parseRegisterPair(OperandVector &Operands);
OperandMatchResultTy parseMovePRegPair(OperandVector &Operands);
OperandMatchResultTy parseRegisterList(OperandVector &Operands);
@@ -235,13 +242,7 @@ class MipsAsmParser : public MCTargetAsmParser {
const MCSubtargetInfo *STI);
void expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
- const MCSubtargetInfo *STI, bool IsLoad, bool IsImmOpnd);
-
- void expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
- const MCSubtargetInfo *STI, bool IsImmOpnd);
-
- void expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
- const MCSubtargetInfo *STI, bool IsImmOpnd);
+ const MCSubtargetInfo *STI, bool IsLoad);
bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
const MCSubtargetInfo *STI);
@@ -255,9 +256,9 @@ class MipsAsmParser : public MCTargetAsmParser {
bool expandCondBranches(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
const MCSubtargetInfo *STI);
- bool expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
- const MCSubtargetInfo *STI, const bool IsMips64,
- const bool Signed);
+ bool expandDivRem(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI, const bool IsMips64,
+ const bool Signed);
bool expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU, SMLoc IDLoc,
MCStreamer &Out, const MCSubtargetInfo *STI);
@@ -348,10 +349,12 @@ class MipsAsmParser : public MCTargetAsmParser {
bool parseSetHardFloatDirective();
bool parseSetMtDirective();
bool parseSetNoMtDirective();
+ bool parseSetNoCRCDirective();
+ bool parseSetNoVirtDirective();
+ bool parseSetNoGINVDirective();
bool parseSetAssignment();
- bool parseDataDirective(unsigned Size, SMLoc L);
bool parseDirectiveGpWord();
bool parseDirectiveGpDWord();
bool parseDirectiveDtpRelWord();
@@ -466,6 +469,7 @@ public:
Match_RequiresSameSrcAndDst,
Match_NoFCCRegisterForCurrentISA,
Match_NonZeroOperandForSync,
+ Match_NonZeroOperandForMTCX,
Match_RequiresPosSizeRange0_32,
Match_RequiresPosSizeRange33_64,
Match_RequiresPosSizeUImm6,
@@ -482,6 +486,9 @@ public:
MCAsmParserExtension::Initialize(parser);
parser.addAliasForDirective(".asciiz", ".asciz");
+ parser.addAliasForDirective(".hword", ".2byte");
+ parser.addAliasForDirective(".word", ".4byte");
+ parser.addAliasForDirective(".dword", ".8byte");
// Initialize the set of available features.
setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
@@ -507,14 +514,13 @@ public:
CpRestoreOffset = -1;
const Triple &TheTriple = sti.getTargetTriple();
- if ((TheTriple.getArch() == Triple::mips) ||
- (TheTriple.getArch() == Triple::mips64))
- IsLittleEndian = false;
- else
- IsLittleEndian = true;
+ IsLittleEndian = TheTriple.isLittleEndian();
if (getSTI().getCPU() == "mips64r6" && inMicroMipsMode())
report_fatal_error("microMIPS64R6 is not supported", false);
+
+ if (!isABI_O32() && inMicroMipsMode())
+ report_fatal_error("microMIPS64 is not supported", false);
}
/// True if all of $fcc0 - $fcc7 exist for the current ISA.
@@ -643,6 +649,18 @@ public:
return getSTI().getFeatureBits()[Mips::FeatureMT];
}
+ bool hasCRC() const {
+ return getSTI().getFeatureBits()[Mips::FeatureCRC];
+ }
+
+ bool hasVirt() const {
+ return getSTI().getFeatureBits()[Mips::FeatureVirt];
+ }
+
+ bool hasGINV() const {
+ return getSTI().getFeatureBits()[Mips::FeatureGINV];
+ }
+
/// Warn if RegIndex is the same as the current AT.
void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
@@ -1297,6 +1315,20 @@ public:
return IsReloc && isShiftedInt<Bits, ShiftAmount>(Res.getConstant());
}
+ bool isMemWithPtrSizeOffset() const {
+ if (!isMem())
+ return false;
+ if (!getMemBase()->isGPRAsmReg())
+ return false;
+ const unsigned PtrBits = AsmParser.getABI().ArePtrs64bit() ? 64 : 32;
+ if (isa<MCTargetExpr>(getMemOff()) ||
+ (isConstantMemOff() && isIntN(PtrBits, getConstantMemOff())))
+ return true;
+ MCValue Res;
+ bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr, nullptr);
+ return IsReloc && isIntN(PtrBits, Res.getConstant());
+ }
+
bool isMemWithGRPMM16Base() const {
return isMem() && getMemBase()->isMM16AsmReg();
}
@@ -1326,9 +1358,11 @@ public:
template <unsigned Bits, unsigned ShiftLeftAmount>
bool isScaledSImm() const {
- if (isConstantImm() && isShiftedInt<Bits, ShiftLeftAmount>(getConstantImm()))
+ if (isConstantImm() &&
+ isShiftedInt<Bits, ShiftLeftAmount>(getConstantImm()))
return true;
- // Operand can also be a symbol or symbol plus offset in case of relocations.
+ // Operand can also be a symbol or symbol plus
+ // offset in case of relocations.
if (Kind != k_Immediate)
return false;
MCValue Res;
@@ -1405,10 +1439,6 @@ public:
return StringRef(Tok.Data, Tok.Length);
}
- bool isRegPair() const {
- return Kind == k_RegPair && RegIdx.Index <= 30;
- }
-
unsigned getReg() const override {
// As a special case until we sort out the definition of div/divu, accept
// $0/$zero here so that MCK_ZERO works correctly.
@@ -1471,7 +1501,7 @@ public:
static std::unique_ptr<MipsOperand>
createNumericReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
SMLoc S, SMLoc E, MipsAsmParser &Parser) {
- DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
+ LLVM_DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
return CreateReg(Index, Str, RegKind_Numeric, RegInfo, S, E, Parser);
}
@@ -2034,7 +2064,8 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
// FIXME: Add support for forward-declared local symbols.
// FIXME: Add expansion for when the LargeGOT option is enabled.
if (JalSym->isInSection() || JalSym->isTemporary() ||
- (JalSym->isELF() && cast<MCSymbolELF>(JalSym)->getBinding() == ELF::STB_LOCAL)) {
+ (JalSym->isELF() &&
+ cast<MCSymbolELF>(JalSym)->getBinding() == ELF::STB_LOCAL)) {
if (isABI_O32()) {
// If it's a local symbol and the O32 ABI is being used, we expand to:
// lw $25, 0($gp)
@@ -2102,10 +2133,10 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
(OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
MCOperand &Op = Inst.getOperand(i);
if (Op.isImm()) {
- int MemOffset = Op.getImm();
+ int64_t MemOffset = Op.getImm();
if (MemOffset < -32768 || MemOffset > 32767) {
// Offset can't exceed 16bit value.
- expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), true);
+ expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad());
return getParser().hasPendingError();
}
} else if (Op.isExpr()) {
@@ -2115,11 +2146,11 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
static_cast<const MCSymbolRefExpr *>(Expr);
if (SR->getKind() == MCSymbolRefExpr::VK_None) {
// Expand symbol.
- expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
+ expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad());
return getParser().hasPendingError();
}
} else if (!isEvaluated(Expr)) {
- expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
+ expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad());
return getParser().hasPendingError();
}
}
@@ -2128,7 +2159,7 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
} // if load/store
if (inMicroMipsMode()) {
- if (MCID.mayLoad()) {
+ if (MCID.mayLoad() && Inst.getOpcode() != Mips::LWP_MM) {
// Try to create 16-bit GP relative load instruction.
for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
const MCOperandInfo &OpInfo = MCID.OpInfo[i];
@@ -2245,13 +2276,18 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
return Error(IDLoc, "immediate operand value out of range");
break;
case Mips::ADDIUPC_MM:
- MCOperand Opnd = Inst.getOperand(1);
+ Opnd = Inst.getOperand(1);
if (!Opnd.isImm())
return Error(IDLoc, "expected immediate operand kind");
- int Imm = Opnd.getImm();
+ Imm = Opnd.getImm();
if ((Imm % 4 != 0) || !isInt<25>(Imm))
return Error(IDLoc, "immediate operand value out of range");
break;
+ case Mips::LWP_MM:
+ case Mips::SWP_MM:
+ if (Inst.getOperand(0).getReg() == Mips::RA)
+ return Error(IDLoc, "invalid operand for instruction");
+ break;
}
}
@@ -2392,20 +2428,28 @@ MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
return expandCondBranches(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
case Mips::SDivMacro:
case Mips::SDivIMacro:
- return expandDiv(Inst, IDLoc, Out, STI, false, true) ? MER_Fail
- : MER_Success;
+ case Mips::SRemMacro:
+ case Mips::SRemIMacro:
+ return expandDivRem(Inst, IDLoc, Out, STI, false, true) ? MER_Fail
+ : MER_Success;
case Mips::DSDivMacro:
case Mips::DSDivIMacro:
- return expandDiv(Inst, IDLoc, Out, STI, true, true) ? MER_Fail
- : MER_Success;
+ case Mips::DSRemMacro:
+ case Mips::DSRemIMacro:
+ return expandDivRem(Inst, IDLoc, Out, STI, true, true) ? MER_Fail
+ : MER_Success;
case Mips::UDivMacro:
case Mips::UDivIMacro:
- return expandDiv(Inst, IDLoc, Out, STI, false, false) ? MER_Fail
- : MER_Success;
+ case Mips::URemMacro:
+ case Mips::URemIMacro:
+ return expandDivRem(Inst, IDLoc, Out, STI, false, false) ? MER_Fail
+ : MER_Success;
case Mips::DUDivMacro:
case Mips::DUDivIMacro:
- return expandDiv(Inst, IDLoc, Out, STI, true, false) ? MER_Fail
- : MER_Success;
+ case Mips::DURemMacro:
+ case Mips::DURemIMacro:
+ return expandDivRem(Inst, IDLoc, Out, STI, true, false) ? MER_Fail
+ : MER_Success;
case Mips::PseudoTRUNC_W_S:
return expandTrunc(Inst, false, false, IDLoc, Out, STI) ? MER_Fail
: MER_Success;
@@ -3522,21 +3566,17 @@ bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
}
void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
- const MCSubtargetInfo *STI, bool IsLoad,
- bool IsImmOpnd) {
- if (IsLoad) {
- expandLoadInst(Inst, IDLoc, Out, STI, IsImmOpnd);
- return;
- }
- expandStoreInst(Inst, IDLoc, Out, STI, IsImmOpnd);
-}
+ const MCSubtargetInfo *STI, bool IsLoad) {
+ const MCOperand &DstRegOp = Inst.getOperand(0);
+ assert(DstRegOp.isReg() && "expected register operand kind");
+ const MCOperand &BaseRegOp = Inst.getOperand(1);
+ assert(BaseRegOp.isReg() && "expected register operand kind");
+ const MCOperand &OffsetOp = Inst.getOperand(2);
-void MipsAsmParser::expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
- const MCSubtargetInfo *STI, bool IsImmOpnd) {
MipsTargetStreamer &TOut = getTargetStreamer();
-
- unsigned DstReg = Inst.getOperand(0).getReg();
- unsigned BaseReg = Inst.getOperand(1).getReg();
+ unsigned DstReg = DstRegOp.getReg();
+ unsigned BaseReg = BaseRegOp.getReg();
+ unsigned TmpReg = DstReg;
const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
int16_t DstRegClass = Desc.OpInfo[0].RegClass;
@@ -3545,75 +3585,51 @@ void MipsAsmParser::expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
bool IsGPR = (DstRegClassID == Mips::GPR32RegClassID) ||
(DstRegClassID == Mips::GPR64RegClassID);
- if (IsImmOpnd) {
- // Try to use DstReg as the temporary.
- if (IsGPR && (BaseReg != DstReg)) {
- TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
- Inst.getOperand(2).getImm(), DstReg, IDLoc,
- STI);
- return;
- }
-
- // At this point we need AT to perform the expansions and we exit if it is
- // not available.
- unsigned ATReg = getATReg(IDLoc);
- if (!ATReg)
+ if (!IsLoad || !IsGPR || (BaseReg == DstReg)) {
+ // At this point we need AT to perform the expansions
+ // and we exit if it is not available.
+ TmpReg = getATReg(IDLoc);
+ if (!TmpReg)
return;
-
- TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
- Inst.getOperand(2).getImm(), ATReg, IDLoc, STI);
- return;
}
- const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
- MCOperand LoOperand = MCOperand::createExpr(
- MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
- MCOperand HiOperand = MCOperand::createExpr(
- MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
+ if (OffsetOp.isImm()) {
+ int64_t LoOffset = OffsetOp.getImm() & 0xffff;
+ int64_t HiOffset = OffsetOp.getImm() & ~0xffff;
- // Try to use DstReg as the temporary.
- if (IsGPR && (BaseReg != DstReg)) {
- TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
- LoOperand, DstReg, IDLoc, STI);
- return;
- }
+ // If msb of LoOffset is 1(negative number) we must increment
+ // HiOffset to account for the sign-extension of the low part.
+ if (LoOffset & 0x8000)
+ HiOffset += 0x10000;
- // At this point we need AT to perform the expansions and we exit if it is
- // not available.
- unsigned ATReg = getATReg(IDLoc);
- if (!ATReg)
- return;
+ bool IsLargeOffset = HiOffset != 0;
- TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
- LoOperand, ATReg, IDLoc, STI);
-}
-
-void MipsAsmParser::expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
- const MCSubtargetInfo *STI,
- bool IsImmOpnd) {
- MipsTargetStreamer &TOut = getTargetStreamer();
-
- unsigned SrcReg = Inst.getOperand(0).getReg();
- unsigned BaseReg = Inst.getOperand(1).getReg();
+ if (IsLargeOffset) {
+ bool Is32BitImm = (HiOffset >> 32) == 0;
+ if (loadImmediate(HiOffset, TmpReg, Mips::NoRegister, Is32BitImm, true,
+ IDLoc, Out, STI))
+ return;
+ }
- if (IsImmOpnd) {
- TOut.emitStoreWithImmOffset(Inst.getOpcode(), SrcReg, BaseReg,
- Inst.getOperand(2).getImm(),
- [&]() { return getATReg(IDLoc); }, IDLoc, STI);
- return;
+ if (BaseReg != Mips::ZERO && BaseReg != Mips::ZERO_64)
+ TOut.emitRRR(isGP64bit() ? Mips::DADDu : Mips::ADDu, TmpReg, TmpReg,
+ BaseReg, IDLoc, STI);
+ TOut.emitRRI(Inst.getOpcode(), DstReg, TmpReg, LoOffset, IDLoc, STI);
+ } else {
+ assert(OffsetOp.isExpr() && "expected expression operand kind");
+ const MCExpr *ExprOffset = OffsetOp.getExpr();
+ MCOperand LoOperand = MCOperand::createExpr(
+ MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
+ MCOperand HiOperand = MCOperand::createExpr(
+ MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
+
+ if (IsLoad)
+ TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
+ LoOperand, TmpReg, IDLoc, STI);
+ else
+ TOut.emitStoreWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
+ LoOperand, TmpReg, IDLoc, STI);
}
-
- unsigned ATReg = getATReg(IDLoc);
- if (!ATReg)
- return;
-
- const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
- MCOperand LoOperand = MCOperand::createExpr(
- MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
- MCOperand HiOperand = MCOperand::createExpr(
- MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
- TOut.emitStoreWithSymOffset(Inst.getOpcode(), SrcReg, BaseReg, HiOperand,
- LoOperand, ATReg, IDLoc, STI);
}
bool MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
@@ -3734,7 +3750,8 @@ bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
case Mips::BLTUL:
AcceptsEquality = false;
ReverseOrderSLT = false;
- IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
+ IsUnsigned =
+ ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
ZeroSrcOpcode = Mips::BGTZ;
ZeroTrgOpcode = Mips::BLTZ;
@@ -3745,7 +3762,8 @@ bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
case Mips::BLEUL:
AcceptsEquality = true;
ReverseOrderSLT = true;
- IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
+ IsUnsigned =
+ ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
ZeroSrcOpcode = Mips::BGEZ;
ZeroTrgOpcode = Mips::BLEZ;
@@ -3756,7 +3774,8 @@ bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
case Mips::BGEUL:
AcceptsEquality = true;
ReverseOrderSLT = false;
- IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
+ IsUnsigned =
+ ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
ZeroSrcOpcode = Mips::BLEZ;
ZeroTrgOpcode = Mips::BGEZ;
@@ -3767,7 +3786,8 @@ bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
case Mips::BGTUL:
AcceptsEquality = false;
ReverseOrderSLT = true;
- IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
+ IsUnsigned =
+ ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
ZeroSrcOpcode = Mips::BLTZ;
ZeroTrgOpcode = Mips::BGTZ;
@@ -3885,7 +3905,7 @@ bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
// This is accomplished by using a BNEZ with the result of the SLT.
//
// The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
- // and BLE with BGT), so we change the BNEZ into a a BEQZ.
+ // and BLE with BGT), so we change the BNEZ into a BEQZ.
// Because only BGE and BLE branch on equality, we can use the
// AcceptsEquality variable to decide when to emit the BEQZ.
// Note that the order of the SLT arguments doesn't change between
@@ -3912,9 +3932,9 @@ bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
// The destination register can only be $zero when expanding (S)DivIMacro or
// D(S)DivMacro.
-bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
- const MCSubtargetInfo *STI, const bool IsMips64,
- const bool Signed) {
+bool MipsAsmParser::expandDivRem(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI, const bool IsMips64,
+ const bool Signed) {
MipsTargetStreamer &TOut = getTargetStreamer();
warnIfNoMacro(IDLoc);
@@ -3954,6 +3974,17 @@ bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
bool UseTraps = useTraps();
+ unsigned Opcode = Inst.getOpcode();
+ bool isDiv = Opcode == Mips::SDivMacro || Opcode == Mips::SDivIMacro ||
+ Opcode == Mips::UDivMacro || Opcode == Mips::UDivIMacro ||
+ Opcode == Mips::DSDivMacro || Opcode == Mips::DSDivIMacro ||
+ Opcode == Mips::DUDivMacro || Opcode == Mips::DUDivIMacro;
+
+ bool isRem = Opcode == Mips::SRemMacro || Opcode == Mips::SRemIMacro ||
+ Opcode == Mips::URemMacro || Opcode == Mips::URemIMacro ||
+ Opcode == Mips::DSRemMacro || Opcode == Mips::DSRemIMacro ||
+ Opcode == Mips::DURemMacro || Opcode == Mips::DURemIMacro;
+
if (RtOp.isImm()) {
unsigned ATReg = getATReg(IDLoc);
if (!ATReg)
@@ -3967,10 +3998,13 @@ bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
return false;
}
- if (ImmValue == 1) {
+ if (isRem && (ImmValue == 1 || (Signed && (ImmValue == -1)))) {
+ TOut.emitRRR(Mips::OR, RdReg, ZeroReg, ZeroReg, IDLoc, STI);
+ return false;
+ } else if (isDiv && ImmValue == 1) {
TOut.emitRRR(Mips::OR, RdReg, RsReg, Mips::ZERO, IDLoc, STI);
return false;
- } else if (Signed && ImmValue == -1) {
+ } else if (isDiv && Signed && ImmValue == -1) {
TOut.emitRRR(SubOp, RdReg, ZeroReg, RsReg, IDLoc, STI);
return false;
} else {
@@ -3978,16 +4012,16 @@ bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
false, Inst.getLoc(), Out, STI))
return true;
TOut.emitRR(DivOp, RsReg, ATReg, IDLoc, STI);
- TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
+ TOut.emitR(isDiv ? Mips::MFLO : Mips::MFHI, RdReg, IDLoc, STI);
return false;
}
return true;
}
- // If the macro expansion of (d)div(u) would always trap or break, insert
- // the trap/break and exit. This gives a different result to GAS. GAS has
- // an inconsistency/missed optimization in that not all cases are handled
- // equivalently. As the observed behaviour is the same, we're ok.
+ // If the macro expansion of (d)div(u) or (d)rem(u) would always trap or
+ // break, insert the trap/break and exit. This gives a different result to
+ // GAS. GAS has an inconsistency/missed optimization in that not all cases
+ // are handled equivalently. As the observed behaviour is the same, we're ok.
if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
if (UseTraps) {
TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI);
@@ -3997,6 +4031,13 @@ bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
return false;
}
+ // (d)rem(u) $0, $X, $Y is a special case. Like div $zero, $X, $Y, it does
+ // not expand to macro sequence.
+ if (isRem && (RdReg == Mips::ZERO || RdReg == Mips::ZERO_64)) {
+ TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
+ return false;
+ }
+
// Temporary label for first branch traget
MCContext &Context = TOut.getStreamer().getContext();
MCSymbol *BrTarget;
@@ -4020,7 +4061,7 @@ bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
if (!UseTraps)
TOut.getStreamer().EmitLabel(BrTarget);
- TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
+ TOut.emitR(isDiv ? Mips::MFLO : Mips::MFHI, RdReg, IDLoc, STI);
return false;
}
@@ -4043,7 +4084,7 @@ bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
if (IsMips64) {
TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, STI);
- TOut.emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, STI);
+ TOut.emitDSLL(ATReg, ATReg, 63, IDLoc, STI);
} else {
TOut.emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, STI);
}
@@ -4053,12 +4094,12 @@ bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
else {
// Branch to the mflo instruction.
TOut.emitRRX(Mips::BNE, RsReg, ATReg, LabelOpEnd, IDLoc, STI);
- TOut.emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, STI);
+ TOut.emitNop(IDLoc, STI);
TOut.emitII(Mips::BREAK, 0x6, 0, IDLoc, STI);
}
TOut.getStreamer().EmitLabel(BrTargetEnd);
- TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
+ TOut.emitR(isDiv ? Mips::MFLO : Mips::MFHI, RdReg, IDLoc, STI);
return false;
}
@@ -4287,7 +4328,8 @@ bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
DstReg = ATReg;
}
- if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Out, STI)) {
+ if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false,
+ Inst.getLoc(), Out, STI)) {
switch (FinalOpcode) {
default:
llvm_unreachable("unimplemented expansion");
@@ -4675,7 +4717,8 @@ bool MipsAsmParser::expandMulImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
if (!ATReg)
return true;
- loadImmediate(ImmValue, ATReg, Mips::NoRegister, true, false, IDLoc, Out, STI);
+ loadImmediate(ImmValue, ATReg, Mips::NoRegister, true, false, IDLoc, Out,
+ STI);
TOut.emitRR(Inst.getOpcode() == Mips::MULImmMacro ? Mips::MULT : Mips::DMULT,
SrcReg, ATReg, IDLoc, STI);
@@ -5136,13 +5179,13 @@ unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
// It also applies for registers Rt and Rs of microMIPSr6 jalrc.hb instruction
// and registers Rd and Base for microMIPS lwp instruction
case Mips::JALR_HB:
+ case Mips::JALR_HB64:
case Mips::JALRC_HB_MMR6:
case Mips::JALRC_MMR6:
if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
return Match_RequiresDifferentSrcAndDst;
return Match_Success;
case Mips::LWP_MM:
- case Mips::LWP_MMR6:
if (Inst.getOperand(0).getReg() == Inst.getOperand(2).getReg())
return Match_RequiresDifferentSrcAndDst;
return Match_Success;
@@ -5150,6 +5193,13 @@ unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
if (Inst.getOperand(0).getImm() != 0 && !hasMips32())
return Match_NonZeroOperandForSync;
return Match_Success;
+ case Mips::MFC0:
+ case Mips::MTC0:
+ case Mips::MTC2:
+ case Mips::MFC2:
+ if (Inst.getOperand(2).getImm() != 0 && !hasMips32())
+ return Match_NonZeroOperandForMTCX;
+ return Match_Success;
// As described the MIPSR6 spec, the compact branches that compare registers
// must:
// a) Not use the zero register.
@@ -5237,6 +5287,13 @@ unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
return Match_RequiresPosSizeRange33_64;
return Match_Success;
}
+ case Mips::CRC32B: case Mips::CRC32CB:
+ case Mips::CRC32H: case Mips::CRC32CH:
+ case Mips::CRC32W: case Mips::CRC32CW:
+ case Mips::CRC32D: case Mips::CRC32CD:
+ if (Inst.getOperand(0).getReg() != Inst.getOperand(2).getReg())
+ return Match_RequiresSameSrcAndDst;
+ return Match_Success;
}
uint64_t TSFlags = getInstDesc(Inst.getOpcode()).TSFlags;
@@ -5290,7 +5347,10 @@ bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
return Error(ErrorLoc, "invalid operand for instruction");
}
case Match_NonZeroOperandForSync:
- return Error(IDLoc, "s-type must be zero or unspecified for pre-MIPS32 ISAs");
+ return Error(IDLoc,
+ "s-type must be zero or unspecified for pre-MIPS32 ISAs");
+ case Match_NonZeroOperandForMTCX:
+ return Error(IDLoc, "selector must be zero for pre-MIPS32 ISAs");
case Match_MnemonicFail:
return Error(IDLoc, "invalid instruction");
case Match_RequiresDifferentSrcAndDst:
@@ -5429,6 +5489,9 @@ bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
case Match_MemSImm16:
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
"expected memory with 16-bit signed offset");
+ case Match_MemSImmPtr:
+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+ "expected memory with 32-bit signed offset");
case Match_RequiresPosSizeRange0_32: {
SMLoc ErrorStart = Operands[3]->getStartLoc();
SMLoc ErrorEnd = Operands[4]->getEndLoc();
@@ -5463,6 +5526,17 @@ void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
Warning(Loc, "macro instruction expanded into multiple instructions");
}
+void MipsAsmParser::ConvertXWPOperands(MCInst &Inst,
+ const OperandVector &Operands) {
+ assert(
+ (Inst.getOpcode() == Mips::LWP_MM || Inst.getOpcode() == Mips::SWP_MM) &&
+ "Unexpected instruction!");
+ ((MipsOperand &)*Operands[1]).addGPR32ZeroAsmRegOperands(Inst, 1);
+ int NextReg = nextReg(((MipsOperand &)*Operands[1]).getGPR32Reg());
+ Inst.addOperand(MCOperand::createReg(NextReg));
+ ((MipsOperand &)*Operands[2]).addMemOperands(Inst, 2);
+}
+
void
MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
SMRange Range, bool ShowColors) {
@@ -5653,7 +5727,7 @@ unsigned MipsAsmParser::getReg(int RC, int RegNo) {
bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
MCAsmParser &Parser = getParser();
- DEBUG(dbgs() << "parseOperand\n");
+ LLVM_DEBUG(dbgs() << "parseOperand\n");
// Check if the current operand has a custom associated parser, if so, try to
// custom parse the operand, or fallback to the general approach.
@@ -5666,7 +5740,7 @@ bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
if (ResTy == MatchOperand_ParseFail)
return true;
- DEBUG(dbgs() << ".. Generic Parser\n");
+ LLVM_DEBUG(dbgs() << ".. Generic Parser\n");
switch (getLexer().getKind()) {
case AsmToken::Dollar: {
@@ -5696,7 +5770,7 @@ bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
return false;
}
default: {
- DEBUG(dbgs() << ".. generic integer expression\n");
+ LLVM_DEBUG(dbgs() << ".. generic integer expression\n");
const MCExpr *Expr;
SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
@@ -5769,7 +5843,7 @@ bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
OperandMatchResultTy
MipsAsmParser::parseMemOperand(OperandVector &Operands) {
MCAsmParser &Parser = getParser();
- DEBUG(dbgs() << "parseMemOperand\n");
+ LLVM_DEBUG(dbgs() << "parseMemOperand\n");
const MCExpr *IdVal = nullptr;
SMLoc S;
bool isParenExpr = false;
@@ -5905,13 +5979,12 @@ MipsAsmParser::parseMemOperand(OperandVector &Operands) {
bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
MCAsmParser &Parser = getParser();
MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
- if (Sym) {
- SMLoc S = Parser.getTok().getLoc();
- const MCExpr *Expr;
- if (Sym->isVariable())
- Expr = Sym->getVariableValue();
- else
- return false;
+ if (!Sym)
+ return false;
+
+ SMLoc S = Parser.getTok().getLoc();
+ if (Sym->isVariable()) {
+ const MCExpr *Expr = Sym->getVariableValue();
if (Expr->getKind() == MCExpr::SymbolRef) {
const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
StringRef DefSymbol = Ref->getSymbol().getName();
@@ -5921,12 +5994,26 @@ bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
if (ResTy == MatchOperand_Success) {
Parser.Lex();
return true;
- } else if (ResTy == MatchOperand_ParseFail)
+ }
+ if (ResTy == MatchOperand_ParseFail)
llvm_unreachable("Should never ParseFail");
- return false;
+ }
+ }
+ } else if (Sym->isUnset()) {
+ // If symbol is unset, it might be created in the `parseSetAssignment`
+ // routine as an alias for a numeric register name.
+ // Lookup in the aliases list.
+ auto Entry = RegisterSets.find(Sym->getName());
+ if (Entry != RegisterSets.end()) {
+ OperandMatchResultTy ResTy =
+ matchAnyRegisterWithoutDollar(Operands, Entry->getValue(), S);
+ if (ResTy == MatchOperand_Success) {
+ Parser.Lex();
+ return true;
}
}
}
+
return false;
}
@@ -5994,48 +6081,59 @@ MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
}
OperandMatchResultTy
-MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
- MCAsmParser &Parser = getParser();
- auto Token = Parser.getLexer().peekTok(false);
-
+MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands,
+ const AsmToken &Token, SMLoc S) {
if (Token.is(AsmToken::Identifier)) {
- DEBUG(dbgs() << ".. identifier\n");
+ LLVM_DEBUG(dbgs() << ".. identifier\n");
StringRef Identifier = Token.getIdentifier();
OperandMatchResultTy ResTy =
matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
return ResTy;
} else if (Token.is(AsmToken::Integer)) {
- DEBUG(dbgs() << ".. integer\n");
+ LLVM_DEBUG(dbgs() << ".. integer\n");
+ int64_t RegNum = Token.getIntVal();
+ if (RegNum < 0 || RegNum > 31) {
+ // Show the error, but treat invalid register
+ // number as a normal one to continue parsing
+ // and catch other possible errors.
+ Error(getLexer().getLoc(), "invalid register number");
+ }
Operands.push_back(MipsOperand::createNumericReg(
- Token.getIntVal(), Token.getString(), getContext().getRegisterInfo(), S,
+ RegNum, Token.getString(), getContext().getRegisterInfo(), S,
Token.getLoc(), *this));
return MatchOperand_Success;
}
- DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
+ LLVM_DEBUG(dbgs() << Token.getKind() << "\n");
return MatchOperand_NoMatch;
}
OperandMatchResultTy
+MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
+ auto Token = getLexer().peekTok(false);
+ return matchAnyRegisterWithoutDollar(Operands, Token, S);
+}
+
+OperandMatchResultTy
MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
MCAsmParser &Parser = getParser();
- DEBUG(dbgs() << "parseAnyRegister\n");
+ LLVM_DEBUG(dbgs() << "parseAnyRegister\n");
auto Token = Parser.getTok();
SMLoc S = Token.getLoc();
if (Token.isNot(AsmToken::Dollar)) {
- DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
+ LLVM_DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
if (Token.is(AsmToken::Identifier)) {
if (searchSymbolAlias(Operands))
return MatchOperand_Success;
}
- DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
+ LLVM_DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
return MatchOperand_NoMatch;
}
- DEBUG(dbgs() << ".. $\n");
+ LLVM_DEBUG(dbgs() << ".. $\n");
OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
if (ResTy == MatchOperand_Success) {
@@ -6048,7 +6146,7 @@ MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
OperandMatchResultTy
MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
MCAsmParser &Parser = getParser();
- DEBUG(dbgs() << "parseJumpTarget\n");
+ LLVM_DEBUG(dbgs() << "parseJumpTarget\n");
SMLoc S = getLexer().getLoc();
@@ -6181,22 +6279,6 @@ MipsAsmParser::parseRegisterList(OperandVector &Operands) {
}
OperandMatchResultTy
-MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
- MCAsmParser &Parser = getParser();
-
- SMLoc S = Parser.getTok().getLoc();
- if (parseAnyRegister(Operands) != MatchOperand_Success)
- return MatchOperand_ParseFail;
-
- SMLoc E = Parser.getTok().getLoc();
- MipsOperand Op = static_cast<MipsOperand &>(*Operands.back());
-
- Operands.pop_back();
- Operands.push_back(MipsOperand::CreateRegPair(Op, S, E, *this));
- return MatchOperand_Success;
-}
-
-OperandMatchResultTy
MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
MCAsmParser &Parser = getParser();
SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
@@ -6292,7 +6374,7 @@ bool MipsAsmParser::parseBracketSuffix(StringRef Name,
bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
SMLoc NameLoc, OperandVector &Operands) {
MCAsmParser &Parser = getParser();
- DEBUG(dbgs() << "ParseInstruction\n");
+ LLVM_DEBUG(dbgs() << "ParseInstruction\n");
// We have reached first instruction, module directive are now forbidden.
getTargetStreamer().forbidModuleDirective();
@@ -6654,6 +6736,57 @@ bool MipsAsmParser::parseSetNoMtDirective() {
return false;
}
+bool MipsAsmParser::parseSetNoCRCDirective() {
+ MCAsmParser &Parser = getParser();
+ Parser.Lex(); // Eat "nocrc".
+
+ // If this is not the end of the statement, report an error.
+ if (getLexer().isNot(AsmToken::EndOfStatement)) {
+ reportParseError("unexpected token, expected end of statement");
+ return false;
+ }
+
+ clearFeatureBits(Mips::FeatureCRC, "crc");
+
+ getTargetStreamer().emitDirectiveSetNoCRC();
+ Parser.Lex(); // Consume the EndOfStatement.
+ return false;
+}
+
+bool MipsAsmParser::parseSetNoVirtDirective() {
+ MCAsmParser &Parser = getParser();
+ Parser.Lex(); // Eat "novirt".
+
+ // If this is not the end of the statement, report an error.
+ if (getLexer().isNot(AsmToken::EndOfStatement)) {
+ reportParseError("unexpected token, expected end of statement");
+ return false;
+ }
+
+ clearFeatureBits(Mips::FeatureVirt, "virt");
+
+ getTargetStreamer().emitDirectiveSetNoVirt();
+ Parser.Lex(); // Consume the EndOfStatement.
+ return false;
+}
+
+bool MipsAsmParser::parseSetNoGINVDirective() {
+ MCAsmParser &Parser = getParser();
+ Parser.Lex(); // Eat "noginv".
+
+ // If this is not the end of the statement, report an error.
+ if (getLexer().isNot(AsmToken::EndOfStatement)) {
+ reportParseError("unexpected token, expected end of statement");
+ return false;
+ }
+
+ clearFeatureBits(Mips::FeatureGINV, "ginv");
+
+ getTargetStreamer().emitDirectiveSetNoGINV();
+ Parser.Lex(); // Consume the EndOfStatement.
+ return false;
+}
+
bool MipsAsmParser::parseSetPopDirective() {
MCAsmParser &Parser = getParser();
SMLoc Loc = getLexer().getLoc();
@@ -6719,17 +6852,30 @@ bool MipsAsmParser::parseSetAssignment() {
MCAsmParser &Parser = getParser();
if (Parser.parseIdentifier(Name))
- reportParseError("expected identifier after .set");
+ return reportParseError("expected identifier after .set");
if (getLexer().isNot(AsmToken::Comma))
return reportParseError("unexpected token, expected comma");
Lex(); // Eat comma
- if (Parser.parseExpression(Value))
+ if (getLexer().is(AsmToken::Dollar) &&
+ getLexer().peekTok().is(AsmToken::Integer)) {
+ // Parse assignment of a numeric register:
+ // .set r1,$1
+ Parser.Lex(); // Eat $.
+ RegisterSets[Name] = Parser.getTok();
+ Parser.Lex(); // Eat identifier.
+ getContext().getOrCreateSymbol(Name);
+ } else if (!Parser.parseExpression(Value)) {
+ // Parse assignment of an expression including
+ // symbolic registers:
+ // .set $tmp, $BB0-$BB1
+ // .set r2, $f2
+ MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
+ Sym->setVariableValue(Value);
+ } else {
return reportParseError("expected valid expression after comma");
-
- MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
- Sym->setVariableValue(Value);
+ }
return false;
}
@@ -6875,6 +7021,18 @@ bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
selectArch("mips64r6");
getTargetStreamer().emitDirectiveSetMips64R6();
break;
+ case Mips::FeatureCRC:
+ setFeatureBits(Mips::FeatureCRC, "crc");
+ getTargetStreamer().emitDirectiveSetCRC();
+ break;
+ case Mips::FeatureVirt:
+ setFeatureBits(Mips::FeatureVirt, "virt");
+ getTargetStreamer().emitDirectiveSetVirt();
+ break;
+ case Mips::FeatureGINV:
+ setFeatureBits(Mips::FeatureGINV, "ginv");
+ getTargetStreamer().emitDirectiveSetGINV();
+ break;
}
return false;
}
@@ -7074,143 +7232,131 @@ bool MipsAsmParser::parseDirectiveNaN() {
}
bool MipsAsmParser::parseDirectiveSet() {
- MCAsmParser &Parser = getParser();
- // Get the next token.
- const AsmToken &Tok = Parser.getTok();
+ const AsmToken &Tok = getParser().getTok();
+ StringRef IdVal = Tok.getString();
+ SMLoc Loc = Tok.getLoc();
- if (Tok.getString() == "noat") {
+ if (IdVal == "noat")
return parseSetNoAtDirective();
- } else if (Tok.getString() == "at") {
+ if (IdVal == "at")
return parseSetAtDirective();
- } else if (Tok.getString() == "arch") {
+ if (IdVal == "arch")
return parseSetArchDirective();
- } else if (Tok.getString() == "bopt") {
- Warning(Tok.getLoc(), "'bopt' feature is unsupported");
+ if (IdVal == "bopt") {
+ Warning(Loc, "'bopt' feature is unsupported");
getParser().Lex();
return false;
- } else if (Tok.getString() == "nobopt") {
+ }
+ if (IdVal == "nobopt") {
// We're already running in nobopt mode, so nothing to do.
getParser().Lex();
return false;
- } else if (Tok.getString() == "fp") {
+ }
+ if (IdVal == "fp")
return parseSetFpDirective();
- } else if (Tok.getString() == "oddspreg") {
+ if (IdVal == "oddspreg")
return parseSetOddSPRegDirective();
- } else if (Tok.getString() == "nooddspreg") {
+ if (IdVal == "nooddspreg")
return parseSetNoOddSPRegDirective();
- } else if (Tok.getString() == "pop") {
+ if (IdVal == "pop")
return parseSetPopDirective();
- } else if (Tok.getString() == "push") {
+ if (IdVal == "push")
return parseSetPushDirective();
- } else if (Tok.getString() == "reorder") {
+ if (IdVal == "reorder")
return parseSetReorderDirective();
- } else if (Tok.getString() == "noreorder") {
+ if (IdVal == "noreorder")
return parseSetNoReorderDirective();
- } else if (Tok.getString() == "macro") {
+ if (IdVal == "macro")
return parseSetMacroDirective();
- } else if (Tok.getString() == "nomacro") {
+ if (IdVal == "nomacro")
return parseSetNoMacroDirective();
- } else if (Tok.getString() == "mips16") {
+ if (IdVal == "mips16")
return parseSetMips16Directive();
- } else if (Tok.getString() == "nomips16") {
+ if (IdVal == "nomips16")
return parseSetNoMips16Directive();
- } else if (Tok.getString() == "nomicromips") {
+ if (IdVal == "nomicromips") {
clearFeatureBits(Mips::FeatureMicroMips, "micromips");
getTargetStreamer().emitDirectiveSetNoMicroMips();
- Parser.eatToEndOfStatement();
+ getParser().eatToEndOfStatement();
return false;
- } else if (Tok.getString() == "micromips") {
+ }
+ if (IdVal == "micromips") {
if (hasMips64r6()) {
- Error(Tok.getLoc(), ".set micromips directive is not supported with MIPS64R6");
+ Error(Loc, ".set micromips directive is not supported with MIPS64R6");
return false;
}
return parseSetFeature(Mips::FeatureMicroMips);
- } else if (Tok.getString() == "mips0") {
+ }
+ if (IdVal == "mips0")
return parseSetMips0Directive();
- } else if (Tok.getString() == "mips1") {
+ if (IdVal == "mips1")
return parseSetFeature(Mips::FeatureMips1);
- } else if (Tok.getString() == "mips2") {
+ if (IdVal == "mips2")
return parseSetFeature(Mips::FeatureMips2);
- } else if (Tok.getString() == "mips3") {
+ if (IdVal == "mips3")
return parseSetFeature(Mips::FeatureMips3);
- } else if (Tok.getString() == "mips4") {
+ if (IdVal == "mips4")
return parseSetFeature(Mips::FeatureMips4);
- } else if (Tok.getString() == "mips5") {
+ if (IdVal == "mips5")
return parseSetFeature(Mips::FeatureMips5);
- } else if (Tok.getString() == "mips32") {
+ if (IdVal == "mips32")
return parseSetFeature(Mips::FeatureMips32);
- } else if (Tok.getString() == "mips32r2") {
+ if (IdVal == "mips32r2")
return parseSetFeature(Mips::FeatureMips32r2);
- } else if (Tok.getString() == "mips32r3") {
+ if (IdVal == "mips32r3")
return parseSetFeature(Mips::FeatureMips32r3);
- } else if (Tok.getString() == "mips32r5") {
+ if (IdVal == "mips32r5")
return parseSetFeature(Mips::FeatureMips32r5);
- } else if (Tok.getString() == "mips32r6") {
+ if (IdVal == "mips32r6")
return parseSetFeature(Mips::FeatureMips32r6);
- } else if (Tok.getString() == "mips64") {
+ if (IdVal == "mips64")
return parseSetFeature(Mips::FeatureMips64);
- } else if (Tok.getString() == "mips64r2") {
+ if (IdVal == "mips64r2")
return parseSetFeature(Mips::FeatureMips64r2);
- } else if (Tok.getString() == "mips64r3") {
+ if (IdVal == "mips64r3")
return parseSetFeature(Mips::FeatureMips64r3);
- } else if (Tok.getString() == "mips64r5") {
+ if (IdVal == "mips64r5")
return parseSetFeature(Mips::FeatureMips64r5);
- } else if (Tok.getString() == "mips64r6") {
+ if (IdVal == "mips64r6") {
if (inMicroMipsMode()) {
- Error(Tok.getLoc(), "MIPS64R6 is not supported with microMIPS");
+ Error(Loc, "MIPS64R6 is not supported with microMIPS");
return false;
}
return parseSetFeature(Mips::FeatureMips64r6);
- } else if (Tok.getString() == "dsp") {
+ }
+ if (IdVal == "dsp")
return parseSetFeature(Mips::FeatureDSP);
- } else if (Tok.getString() == "dspr2") {
+ if (IdVal == "dspr2")
return parseSetFeature(Mips::FeatureDSPR2);
- } else if (Tok.getString() == "nodsp") {
+ if (IdVal == "nodsp")
return parseSetNoDspDirective();
- } else if (Tok.getString() == "msa") {
+ if (IdVal == "msa")
return parseSetMsaDirective();
- } else if (Tok.getString() == "nomsa") {
+ if (IdVal == "nomsa")
return parseSetNoMsaDirective();
- } else if (Tok.getString() == "mt") {
+ if (IdVal == "mt")
return parseSetMtDirective();
- } else if (Tok.getString() == "nomt") {
+ if (IdVal == "nomt")
return parseSetNoMtDirective();
- } else if (Tok.getString() == "softfloat") {
+ if (IdVal == "softfloat")
return parseSetSoftFloatDirective();
- } else if (Tok.getString() == "hardfloat") {
+ if (IdVal == "hardfloat")
return parseSetHardFloatDirective();
- } else {
- // It is just an identifier, look for an assignment.
- parseSetAssignment();
- return false;
- }
-
- return true;
-}
-
-/// parseDataDirective
-/// ::= .word [ expression (, expression)* ]
-bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
- MCAsmParser &Parser = getParser();
- if (getLexer().isNot(AsmToken::EndOfStatement)) {
- while (true) {
- const MCExpr *Value;
- if (getParser().parseExpression(Value))
- return true;
-
- getParser().getStreamer().EmitValue(Value, Size);
-
- if (getLexer().is(AsmToken::EndOfStatement))
- break;
-
- if (getLexer().isNot(AsmToken::Comma))
- return Error(L, "unexpected token, expected comma");
- Parser.Lex();
- }
- }
-
- Parser.Lex();
- return false;
+ if (IdVal == "crc")
+ return parseSetFeature(Mips::FeatureCRC);
+ if (IdVal == "nocrc")
+ return parseSetNoCRCDirective();
+ if (IdVal == "virt")
+ return parseSetFeature(Mips::FeatureVirt);
+ if (IdVal == "novirt")
+ return parseSetNoVirtDirective();
+ if (IdVal == "ginv")
+ return parseSetFeature(Mips::FeatureGINV);
+ if (IdVal == "noginv")
+ return parseSetNoGINVDirective();
+
+ // It is just an identifier, look for an assignment.
+ return parseSetAssignment();
}
/// parseDirectiveGpWord
@@ -7425,6 +7571,12 @@ bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) {
/// ::= .module softfloat
/// ::= .module hardfloat
/// ::= .module mt
+/// ::= .module crc
+/// ::= .module nocrc
+/// ::= .module virt
+/// ::= .module novirt
+/// ::= .module ginv
+/// ::= .module noginv
bool MipsAsmParser::parseDirectiveModule() {
MCAsmParser &Parser = getParser();
MCAsmLexer &Lexer = getLexer();
@@ -7543,6 +7695,120 @@ bool MipsAsmParser::parseDirectiveModule() {
}
return false; // parseDirectiveModule has finished successfully.
+ } else if (Option == "crc") {
+ setModuleFeatureBits(Mips::FeatureCRC, "crc");
+
+ // Synchronize the ABI Flags information with the FeatureBits information we
+ // updated above.
+ getTargetStreamer().updateABIInfo(*this);
+
+ // If printing assembly, use the recently updated ABI Flags information.
+ // If generating ELF, don't do anything (the .MIPS.abiflags section gets
+ // emitted later).
+ getTargetStreamer().emitDirectiveModuleCRC();
+
+ // If this is not the end of the statement, report an error.
+ if (getLexer().isNot(AsmToken::EndOfStatement)) {
+ reportParseError("unexpected token, expected end of statement");
+ return false;
+ }
+
+ return false; // parseDirectiveModule has finished successfully.
+ } else if (Option == "nocrc") {
+ clearModuleFeatureBits(Mips::FeatureCRC, "crc");
+
+ // Synchronize the ABI Flags information with the FeatureBits information we
+ // updated above.
+ getTargetStreamer().updateABIInfo(*this);
+
+ // If printing assembly, use the recently updated ABI Flags information.
+ // If generating ELF, don't do anything (the .MIPS.abiflags section gets
+ // emitted later).
+ getTargetStreamer().emitDirectiveModuleNoCRC();
+
+ // If this is not the end of the statement, report an error.
+ if (getLexer().isNot(AsmToken::EndOfStatement)) {
+ reportParseError("unexpected token, expected end of statement");
+ return false;
+ }
+
+ return false; // parseDirectiveModule has finished successfully.
+ } else if (Option == "virt") {
+ setModuleFeatureBits(Mips::FeatureVirt, "virt");
+
+ // Synchronize the ABI Flags information with the FeatureBits information we
+ // updated above.
+ getTargetStreamer().updateABIInfo(*this);
+
+ // If printing assembly, use the recently updated ABI Flags information.
+ // If generating ELF, don't do anything (the .MIPS.abiflags section gets
+ // emitted later).
+ getTargetStreamer().emitDirectiveModuleVirt();
+
+ // If this is not the end of the statement, report an error.
+ if (getLexer().isNot(AsmToken::EndOfStatement)) {
+ reportParseError("unexpected token, expected end of statement");
+ return false;
+ }
+
+ return false; // parseDirectiveModule has finished successfully.
+ } else if (Option == "novirt") {
+ clearModuleFeatureBits(Mips::FeatureVirt, "virt");
+
+ // Synchronize the ABI Flags information with the FeatureBits information we
+ // updated above.
+ getTargetStreamer().updateABIInfo(*this);
+
+ // If printing assembly, use the recently updated ABI Flags information.
+ // If generating ELF, don't do anything (the .MIPS.abiflags section gets
+ // emitted later).
+ getTargetStreamer().emitDirectiveModuleNoVirt();
+
+ // If this is not the end of the statement, report an error.
+ if (getLexer().isNot(AsmToken::EndOfStatement)) {
+ reportParseError("unexpected token, expected end of statement");
+ return false;
+ }
+
+ return false; // parseDirectiveModule has finished successfully.
+ } else if (Option == "ginv") {
+ setModuleFeatureBits(Mips::FeatureGINV, "ginv");
+
+ // Synchronize the ABI Flags information with the FeatureBits information we
+ // updated above.
+ getTargetStreamer().updateABIInfo(*this);
+
+ // If printing assembly, use the recently updated ABI Flags information.
+ // If generating ELF, don't do anything (the .MIPS.abiflags section gets
+ // emitted later).
+ getTargetStreamer().emitDirectiveModuleGINV();
+
+ // If this is not the end of the statement, report an error.
+ if (getLexer().isNot(AsmToken::EndOfStatement)) {
+ reportParseError("unexpected token, expected end of statement");
+ return false;
+ }
+
+ return false; // parseDirectiveModule has finished successfully.
+ } else if (Option == "noginv") {
+ clearModuleFeatureBits(Mips::FeatureGINV, "ginv");
+
+ // Synchronize the ABI Flags information with the FeatureBits information we
+ // updated above.
+ getTargetStreamer().updateABIInfo(*this);
+
+ // If printing assembly, use the recently updated ABI Flags information.
+ // If generating ELF, don't do anything (the .MIPS.abiflags section gets
+ // emitted later).
+ getTargetStreamer().emitDirectiveModuleNoGINV();
+
+ // If this is not the end of the statement, report an error.
+ if (getLexer().isNot(AsmToken::EndOfStatement)) {
+ reportParseError("unexpected token, expected end of statement");
+ return false;
+ }
+
+ return false; // parseDirectiveModule has finished successfully.
} else {
return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
}
@@ -7672,10 +7938,6 @@ bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
parseDirectiveCpRestore(DirectiveID.getLoc());
return false;
}
- if (IDVal == ".dword") {
- parseDataDirective(8, DirectiveID.getLoc());
- return false;
- }
if (IDVal == ".ent") {
StringRef SymbolName;
@@ -7923,16 +8185,6 @@ bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
return false;
}
- if (IDVal == ".word") {
- parseDataDirective(4, DirectiveID.getLoc());
- return false;
- }
-
- if (IDVal == ".hword") {
- parseDataDirective(2, DirectiveID.getLoc());
- return false;
- }
-
if (IDVal == ".option") {
parseDirectiveOption();
return false;