diff options
Diffstat (limited to 'lib/Target/Mips/AsmParser/MipsAsmParser.cpp')
-rw-r--r-- | lib/Target/Mips/AsmParser/MipsAsmParser.cpp | 814 |
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; |