10b57cec5SDimitry Andric //===-- MipsAsmParser.cpp - Parse Mips assembly to MCInst instructions ----===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric
90b57cec5SDimitry Andric #include "MCTargetDesc/MipsABIFlagsSection.h"
100b57cec5SDimitry Andric #include "MCTargetDesc/MipsABIInfo.h"
110b57cec5SDimitry Andric #include "MCTargetDesc/MipsBaseInfo.h"
120b57cec5SDimitry Andric #include "MCTargetDesc/MipsMCExpr.h"
130b57cec5SDimitry Andric #include "MCTargetDesc/MipsMCTargetDesc.h"
140b57cec5SDimitry Andric #include "MipsTargetStreamer.h"
150b57cec5SDimitry Andric #include "TargetInfo/MipsTargetInfo.h"
160b57cec5SDimitry Andric #include "llvm/ADT/APFloat.h"
170b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
180b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
190b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
200b57cec5SDimitry Andric #include "llvm/ADT/StringSwitch.h"
210b57cec5SDimitry Andric #include "llvm/ADT/Twine.h"
220b57cec5SDimitry Andric #include "llvm/BinaryFormat/ELF.h"
230b57cec5SDimitry Andric #include "llvm/MC/MCContext.h"
240b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h"
250b57cec5SDimitry Andric #include "llvm/MC/MCInst.h"
260b57cec5SDimitry Andric #include "llvm/MC/MCInstrDesc.h"
2781ad6265SDimitry Andric #include "llvm/MC/MCInstrInfo.h"
280b57cec5SDimitry Andric #include "llvm/MC/MCObjectFileInfo.h"
290b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCAsmLexer.h"
300b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCAsmParser.h"
310b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCAsmParserExtension.h"
320b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCAsmParserUtils.h"
330b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
340b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCTargetAsmParser.h"
350b57cec5SDimitry Andric #include "llvm/MC/MCSectionELF.h"
360b57cec5SDimitry Andric #include "llvm/MC/MCStreamer.h"
370b57cec5SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
380b57cec5SDimitry Andric #include "llvm/MC/MCSymbol.h"
390b57cec5SDimitry Andric #include "llvm/MC/MCSymbolELF.h"
400b57cec5SDimitry Andric #include "llvm/MC/MCValue.h"
41349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h"
428bcb0991SDimitry Andric #include "llvm/Support/Alignment.h"
430b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
440b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
450b57cec5SDimitry Andric #include "llvm/Support/Compiler.h"
460b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
470b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
480b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h"
490b57cec5SDimitry Andric #include "llvm/Support/SMLoc.h"
500b57cec5SDimitry Andric #include "llvm/Support/SourceMgr.h"
510b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
5206c3fb27SDimitry Andric #include "llvm/TargetParser/SubtargetFeature.h"
5306c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h"
540b57cec5SDimitry Andric #include <algorithm>
550b57cec5SDimitry Andric #include <cassert>
560b57cec5SDimitry Andric #include <cstdint>
570b57cec5SDimitry Andric #include <memory>
580b57cec5SDimitry Andric #include <string>
590b57cec5SDimitry Andric #include <utility>
600b57cec5SDimitry Andric
610b57cec5SDimitry Andric using namespace llvm;
620b57cec5SDimitry Andric
630b57cec5SDimitry Andric #define DEBUG_TYPE "mips-asm-parser"
640b57cec5SDimitry Andric
650b57cec5SDimitry Andric namespace llvm {
660b57cec5SDimitry Andric
670b57cec5SDimitry Andric class MCInstrInfo;
680b57cec5SDimitry Andric
690b57cec5SDimitry Andric } // end namespace llvm
700b57cec5SDimitry Andric
710b57cec5SDimitry Andric extern cl::opt<bool> EmitJalrReloc;
720b57cec5SDimitry Andric
730b57cec5SDimitry Andric namespace {
740b57cec5SDimitry Andric
750b57cec5SDimitry Andric class MipsAssemblerOptions {
760b57cec5SDimitry Andric public:
MipsAssemblerOptions(const FeatureBitset & Features_)770b57cec5SDimitry Andric MipsAssemblerOptions(const FeatureBitset &Features_) : Features(Features_) {}
780b57cec5SDimitry Andric
MipsAssemblerOptions(const MipsAssemblerOptions * Opts)790b57cec5SDimitry Andric MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
800b57cec5SDimitry Andric ATReg = Opts->getATRegIndex();
810b57cec5SDimitry Andric Reorder = Opts->isReorder();
820b57cec5SDimitry Andric Macro = Opts->isMacro();
830b57cec5SDimitry Andric Features = Opts->getFeatures();
840b57cec5SDimitry Andric }
850b57cec5SDimitry Andric
getATRegIndex() const860b57cec5SDimitry Andric unsigned getATRegIndex() const { return ATReg; }
setATRegIndex(unsigned Reg)870b57cec5SDimitry Andric bool setATRegIndex(unsigned Reg) {
880b57cec5SDimitry Andric if (Reg > 31)
890b57cec5SDimitry Andric return false;
900b57cec5SDimitry Andric
910b57cec5SDimitry Andric ATReg = Reg;
920b57cec5SDimitry Andric return true;
930b57cec5SDimitry Andric }
940b57cec5SDimitry Andric
isReorder() const950b57cec5SDimitry Andric bool isReorder() const { return Reorder; }
setReorder()960b57cec5SDimitry Andric void setReorder() { Reorder = true; }
setNoReorder()970b57cec5SDimitry Andric void setNoReorder() { Reorder = false; }
980b57cec5SDimitry Andric
isMacro() const990b57cec5SDimitry Andric bool isMacro() const { return Macro; }
setMacro()1000b57cec5SDimitry Andric void setMacro() { Macro = true; }
setNoMacro()1010b57cec5SDimitry Andric void setNoMacro() { Macro = false; }
1020b57cec5SDimitry Andric
getFeatures() const1030b57cec5SDimitry Andric const FeatureBitset &getFeatures() const { return Features; }
setFeatures(const FeatureBitset & Features_)1040b57cec5SDimitry Andric void setFeatures(const FeatureBitset &Features_) { Features = Features_; }
1050b57cec5SDimitry Andric
1060b57cec5SDimitry Andric // Set of features that are either architecture features or referenced
1070b57cec5SDimitry Andric // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6).
1080b57cec5SDimitry Andric // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
1090b57cec5SDimitry Andric // The reason we need this mask is explained in the selectArch function.
1100b57cec5SDimitry Andric // FIXME: Ideally we would like TableGen to generate this information.
1110b57cec5SDimitry Andric static const FeatureBitset AllArchRelatedMask;
1120b57cec5SDimitry Andric
1130b57cec5SDimitry Andric private:
1140b57cec5SDimitry Andric unsigned ATReg = 1;
1150b57cec5SDimitry Andric bool Reorder = true;
1160b57cec5SDimitry Andric bool Macro = true;
1170b57cec5SDimitry Andric FeatureBitset Features;
1180b57cec5SDimitry Andric };
1190b57cec5SDimitry Andric
1200b57cec5SDimitry Andric } // end anonymous namespace
1210b57cec5SDimitry Andric
1220b57cec5SDimitry Andric const FeatureBitset MipsAssemblerOptions::AllArchRelatedMask = {
1230b57cec5SDimitry Andric Mips::FeatureMips1, Mips::FeatureMips2, Mips::FeatureMips3,
1240b57cec5SDimitry Andric Mips::FeatureMips3_32, Mips::FeatureMips3_32r2, Mips::FeatureMips4,
1250b57cec5SDimitry Andric Mips::FeatureMips4_32, Mips::FeatureMips4_32r2, Mips::FeatureMips5,
1260b57cec5SDimitry Andric Mips::FeatureMips5_32r2, Mips::FeatureMips32, Mips::FeatureMips32r2,
1270b57cec5SDimitry Andric Mips::FeatureMips32r3, Mips::FeatureMips32r5, Mips::FeatureMips32r6,
1280b57cec5SDimitry Andric Mips::FeatureMips64, Mips::FeatureMips64r2, Mips::FeatureMips64r3,
1290b57cec5SDimitry Andric Mips::FeatureMips64r5, Mips::FeatureMips64r6, Mips::FeatureCnMips,
1300b57cec5SDimitry Andric Mips::FeatureCnMipsP, Mips::FeatureFP64Bit, Mips::FeatureGP64Bit,
1310b57cec5SDimitry Andric Mips::FeatureNaN2008
1320b57cec5SDimitry Andric };
1330b57cec5SDimitry Andric
1340b57cec5SDimitry Andric namespace {
1350b57cec5SDimitry Andric
1360b57cec5SDimitry Andric class MipsAsmParser : public MCTargetAsmParser {
getTargetStreamer()1370b57cec5SDimitry Andric MipsTargetStreamer &getTargetStreamer() {
138480093f4SDimitry Andric assert(getParser().getStreamer().getTargetStreamer() &&
139480093f4SDimitry Andric "do not have a target streamer");
1400b57cec5SDimitry Andric MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
1410b57cec5SDimitry Andric return static_cast<MipsTargetStreamer &>(TS);
1420b57cec5SDimitry Andric }
1430b57cec5SDimitry Andric
1440b57cec5SDimitry Andric MipsABIInfo ABI;
1450b57cec5SDimitry Andric SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
1460b57cec5SDimitry Andric MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
1470b57cec5SDimitry Andric // nullptr, which indicates that no function is currently
1480b57cec5SDimitry Andric // selected. This usually happens after an '.end func'
1490b57cec5SDimitry Andric // directive.
1500b57cec5SDimitry Andric bool IsLittleEndian;
1510b57cec5SDimitry Andric bool IsPicEnabled;
1520b57cec5SDimitry Andric bool IsCpRestoreSet;
1534c2d3b02SDimitry Andric bool CurForbiddenSlotAttr;
1540b57cec5SDimitry Andric int CpRestoreOffset;
1550b57cec5SDimitry Andric unsigned GPReg;
1560b57cec5SDimitry Andric unsigned CpSaveLocation;
1570b57cec5SDimitry Andric /// If true, then CpSaveLocation is a register, otherwise it's an offset.
1580b57cec5SDimitry Andric bool CpSaveLocationIsRegister;
1590b57cec5SDimitry Andric
1600b57cec5SDimitry Andric // Map of register aliases created via the .set directive.
1610b57cec5SDimitry Andric StringMap<AsmToken> RegisterSets;
1620b57cec5SDimitry Andric
1630b57cec5SDimitry Andric // Print a warning along with its fix-it message at the given range.
1640b57cec5SDimitry Andric void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
1650b57cec5SDimitry Andric SMRange Range, bool ShowColors = true);
1660b57cec5SDimitry Andric
1670b57cec5SDimitry Andric void ConvertXWPOperands(MCInst &Inst, const OperandVector &Operands);
1680b57cec5SDimitry Andric
1690b57cec5SDimitry Andric #define GET_ASSEMBLER_HEADER
1700b57cec5SDimitry Andric #include "MipsGenAsmMatcher.inc"
1710b57cec5SDimitry Andric
1720b57cec5SDimitry Andric unsigned
1730b57cec5SDimitry Andric checkEarlyTargetMatchPredicate(MCInst &Inst,
1740b57cec5SDimitry Andric const OperandVector &Operands) override;
1750b57cec5SDimitry Andric unsigned checkTargetMatchPredicate(MCInst &Inst) override;
1760b57cec5SDimitry Andric
1770b57cec5SDimitry Andric bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1780b57cec5SDimitry Andric OperandVector &Operands, MCStreamer &Out,
1790b57cec5SDimitry Andric uint64_t &ErrorInfo,
1800b57cec5SDimitry Andric bool MatchingInlineAsm) override;
1810b57cec5SDimitry Andric
1820b57cec5SDimitry Andric /// Parse a register as used in CFI directives
1835f757f3fSDimitry Andric bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
1845f757f3fSDimitry Andric ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
1855ffd83dbSDimitry Andric SMLoc &EndLoc) override;
1860b57cec5SDimitry Andric
1870b57cec5SDimitry Andric bool parseParenSuffix(StringRef Name, OperandVector &Operands);
1880b57cec5SDimitry Andric
1890b57cec5SDimitry Andric bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
1900b57cec5SDimitry Andric
1910b57cec5SDimitry Andric bool mnemonicIsValid(StringRef Mnemonic, unsigned VariantID);
1920b57cec5SDimitry Andric
1930b57cec5SDimitry Andric bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
1940b57cec5SDimitry Andric SMLoc NameLoc, OperandVector &Operands) override;
1950b57cec5SDimitry Andric
1960b57cec5SDimitry Andric bool ParseDirective(AsmToken DirectiveID) override;
1970b57cec5SDimitry Andric
19806c3fb27SDimitry Andric ParseStatus parseMemOperand(OperandVector &Operands);
19906c3fb27SDimitry Andric ParseStatus matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
2000b57cec5SDimitry Andric StringRef Identifier, SMLoc S);
20106c3fb27SDimitry Andric ParseStatus matchAnyRegisterWithoutDollar(OperandVector &Operands,
20206c3fb27SDimitry Andric const AsmToken &Token, SMLoc S);
20306c3fb27SDimitry Andric ParseStatus matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S);
20406c3fb27SDimitry Andric ParseStatus parseAnyRegister(OperandVector &Operands);
20506c3fb27SDimitry Andric ParseStatus parseImm(OperandVector &Operands);
20606c3fb27SDimitry Andric ParseStatus parseJumpTarget(OperandVector &Operands);
20706c3fb27SDimitry Andric ParseStatus parseInvNum(OperandVector &Operands);
20806c3fb27SDimitry Andric ParseStatus parseRegisterList(OperandVector &Operands);
2090b57cec5SDimitry Andric
2100b57cec5SDimitry Andric bool searchSymbolAlias(OperandVector &Operands);
2110b57cec5SDimitry Andric
2120b57cec5SDimitry Andric bool parseOperand(OperandVector &, StringRef Mnemonic);
2130b57cec5SDimitry Andric
2140b57cec5SDimitry Andric enum MacroExpanderResultTy {
2150b57cec5SDimitry Andric MER_NotAMacro,
2160b57cec5SDimitry Andric MER_Success,
2170b57cec5SDimitry Andric MER_Fail,
2180b57cec5SDimitry Andric };
2190b57cec5SDimitry Andric
2200b57cec5SDimitry Andric // Expands assembly pseudo instructions.
2210b57cec5SDimitry Andric MacroExpanderResultTy tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
2220b57cec5SDimitry Andric MCStreamer &Out,
2230b57cec5SDimitry Andric const MCSubtargetInfo *STI);
2240b57cec5SDimitry Andric
2250b57cec5SDimitry Andric bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2260b57cec5SDimitry Andric const MCSubtargetInfo *STI);
2270b57cec5SDimitry Andric
2280b57cec5SDimitry Andric bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg,
2290b57cec5SDimitry Andric bool Is32BitImm, bool IsAddress, SMLoc IDLoc,
2300b57cec5SDimitry Andric MCStreamer &Out, const MCSubtargetInfo *STI);
2310b57cec5SDimitry Andric
2320b57cec5SDimitry Andric bool loadAndAddSymbolAddress(const MCExpr *SymExpr, unsigned DstReg,
2330b57cec5SDimitry Andric unsigned SrcReg, bool Is32BitSym, SMLoc IDLoc,
2340b57cec5SDimitry Andric MCStreamer &Out, const MCSubtargetInfo *STI);
2350b57cec5SDimitry Andric
2360b57cec5SDimitry Andric bool emitPartialAddress(MipsTargetStreamer &TOut, SMLoc IDLoc, MCSymbol *Sym);
2370b57cec5SDimitry Andric
2380b57cec5SDimitry Andric bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
2390b57cec5SDimitry Andric MCStreamer &Out, const MCSubtargetInfo *STI);
2400b57cec5SDimitry Andric
241c14a5a88SDimitry Andric bool expandLoadSingleImmToGPR(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2420b57cec5SDimitry Andric const MCSubtargetInfo *STI);
243c14a5a88SDimitry Andric bool expandLoadSingleImmToFPR(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
244c14a5a88SDimitry Andric const MCSubtargetInfo *STI);
245c14a5a88SDimitry Andric bool expandLoadDoubleImmToGPR(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
246c14a5a88SDimitry Andric const MCSubtargetInfo *STI);
247c14a5a88SDimitry Andric bool expandLoadDoubleImmToFPR(MCInst &Inst, bool Is64FPU, SMLoc IDLoc,
248c14a5a88SDimitry Andric MCStreamer &Out, const MCSubtargetInfo *STI);
2490b57cec5SDimitry Andric
2500b57cec5SDimitry Andric bool expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2510b57cec5SDimitry Andric const MCOperand &Offset, bool Is32BitAddress,
2520b57cec5SDimitry Andric SMLoc IDLoc, MCStreamer &Out,
2530b57cec5SDimitry Andric const MCSubtargetInfo *STI);
2540b57cec5SDimitry Andric
2550b57cec5SDimitry Andric bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2560b57cec5SDimitry Andric const MCSubtargetInfo *STI);
2570b57cec5SDimitry Andric
258480093f4SDimitry Andric void expandMem16Inst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
259480093f4SDimitry Andric const MCSubtargetInfo *STI, bool IsLoad);
260480093f4SDimitry Andric void expandMem9Inst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2610b57cec5SDimitry Andric const MCSubtargetInfo *STI, bool IsLoad);
2620b57cec5SDimitry Andric
2630b57cec5SDimitry Andric bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2640b57cec5SDimitry Andric const MCSubtargetInfo *STI);
2650b57cec5SDimitry Andric
2660b57cec5SDimitry Andric bool expandAliasImmediate(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2670b57cec5SDimitry Andric const MCSubtargetInfo *STI);
2680b57cec5SDimitry Andric
2690b57cec5SDimitry Andric bool expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2700b57cec5SDimitry Andric const MCSubtargetInfo *STI);
2710b57cec5SDimitry Andric
2720b57cec5SDimitry Andric bool expandCondBranches(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2730b57cec5SDimitry Andric const MCSubtargetInfo *STI);
2740b57cec5SDimitry Andric
2750b57cec5SDimitry Andric bool expandDivRem(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2760b57cec5SDimitry Andric const MCSubtargetInfo *STI, const bool IsMips64,
2770b57cec5SDimitry Andric const bool Signed);
2780b57cec5SDimitry Andric
2790b57cec5SDimitry Andric bool expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU, SMLoc IDLoc,
2800b57cec5SDimitry Andric MCStreamer &Out, const MCSubtargetInfo *STI);
2810b57cec5SDimitry Andric
2820b57cec5SDimitry Andric bool expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc, MCStreamer &Out,
2830b57cec5SDimitry Andric const MCSubtargetInfo *STI);
2840b57cec5SDimitry Andric
2850b57cec5SDimitry Andric bool expandUsh(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2860b57cec5SDimitry Andric const MCSubtargetInfo *STI);
2870b57cec5SDimitry Andric
2880b57cec5SDimitry Andric bool expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2890b57cec5SDimitry Andric const MCSubtargetInfo *STI);
2900b57cec5SDimitry Andric
2910b57cec5SDimitry Andric bool expandSge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2920b57cec5SDimitry Andric const MCSubtargetInfo *STI);
2930b57cec5SDimitry Andric
2940b57cec5SDimitry Andric bool expandSgeImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2950b57cec5SDimitry Andric const MCSubtargetInfo *STI);
2960b57cec5SDimitry Andric
2970b57cec5SDimitry Andric bool expandSgtImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2980b57cec5SDimitry Andric const MCSubtargetInfo *STI);
2990b57cec5SDimitry Andric
3005ffd83dbSDimitry Andric bool expandSle(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3015ffd83dbSDimitry Andric const MCSubtargetInfo *STI);
3025ffd83dbSDimitry Andric
3035ffd83dbSDimitry Andric bool expandSleImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3045ffd83dbSDimitry Andric const MCSubtargetInfo *STI);
3055ffd83dbSDimitry Andric
3060b57cec5SDimitry Andric bool expandRotation(MCInst &Inst, SMLoc IDLoc,
3070b57cec5SDimitry Andric MCStreamer &Out, const MCSubtargetInfo *STI);
3080b57cec5SDimitry Andric bool expandRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3090b57cec5SDimitry Andric const MCSubtargetInfo *STI);
3100b57cec5SDimitry Andric bool expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3110b57cec5SDimitry Andric const MCSubtargetInfo *STI);
3120b57cec5SDimitry Andric bool expandDRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3130b57cec5SDimitry Andric const MCSubtargetInfo *STI);
3140b57cec5SDimitry Andric
3150b57cec5SDimitry Andric bool expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3160b57cec5SDimitry Andric const MCSubtargetInfo *STI);
3170b57cec5SDimitry Andric
3180b57cec5SDimitry Andric bool expandMulImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3190b57cec5SDimitry Andric const MCSubtargetInfo *STI);
3200b57cec5SDimitry Andric
3210b57cec5SDimitry Andric bool expandMulO(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3220b57cec5SDimitry Andric const MCSubtargetInfo *STI);
3230b57cec5SDimitry Andric
3240b57cec5SDimitry Andric bool expandMulOU(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3250b57cec5SDimitry Andric const MCSubtargetInfo *STI);
3260b57cec5SDimitry Andric
3270b57cec5SDimitry Andric bool expandDMULMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3280b57cec5SDimitry Andric const MCSubtargetInfo *STI);
3290b57cec5SDimitry Andric
3300b57cec5SDimitry Andric bool expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3310b57cec5SDimitry Andric const MCSubtargetInfo *STI, bool IsLoad);
3320b57cec5SDimitry Andric
3330b57cec5SDimitry Andric bool expandStoreDM1Macro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3340b57cec5SDimitry Andric const MCSubtargetInfo *STI);
3350b57cec5SDimitry Andric
3360b57cec5SDimitry Andric bool expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3370b57cec5SDimitry Andric const MCSubtargetInfo *STI);
3380b57cec5SDimitry Andric
3390b57cec5SDimitry Andric bool expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3400b57cec5SDimitry Andric const MCSubtargetInfo *STI);
3410b57cec5SDimitry Andric
3425ffd83dbSDimitry Andric bool expandSne(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3435ffd83dbSDimitry Andric const MCSubtargetInfo *STI);
3445ffd83dbSDimitry Andric
3455ffd83dbSDimitry Andric bool expandSneI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3465ffd83dbSDimitry Andric const MCSubtargetInfo *STI);
3475ffd83dbSDimitry Andric
3480b57cec5SDimitry Andric bool expandMXTRAlias(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3490b57cec5SDimitry Andric const MCSubtargetInfo *STI);
3500b57cec5SDimitry Andric
3510b57cec5SDimitry Andric bool expandSaaAddr(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3520b57cec5SDimitry Andric const MCSubtargetInfo *STI);
3530b57cec5SDimitry Andric
354e8d8bef9SDimitry Andric bool reportParseError(const Twine &ErrorMsg);
355e8d8bef9SDimitry Andric bool reportParseError(SMLoc Loc, const Twine &ErrorMsg);
3560b57cec5SDimitry Andric
3570b57cec5SDimitry Andric bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
3580b57cec5SDimitry Andric
3590b57cec5SDimitry Andric bool parseSetMips0Directive();
3600b57cec5SDimitry Andric bool parseSetArchDirective();
3610b57cec5SDimitry Andric bool parseSetFeature(uint64_t Feature);
3620b57cec5SDimitry Andric bool isPicAndNotNxxAbi(); // Used by .cpload, .cprestore, and .cpsetup.
3635ffd83dbSDimitry Andric bool parseDirectiveCpAdd(SMLoc Loc);
3640b57cec5SDimitry Andric bool parseDirectiveCpLoad(SMLoc Loc);
3650b57cec5SDimitry Andric bool parseDirectiveCpLocal(SMLoc Loc);
3660b57cec5SDimitry Andric bool parseDirectiveCpRestore(SMLoc Loc);
3670b57cec5SDimitry Andric bool parseDirectiveCPSetup();
3680b57cec5SDimitry Andric bool parseDirectiveCPReturn();
3690b57cec5SDimitry Andric bool parseDirectiveNaN();
3700b57cec5SDimitry Andric bool parseDirectiveSet();
3710b57cec5SDimitry Andric bool parseDirectiveOption();
3720b57cec5SDimitry Andric bool parseInsnDirective();
3730b57cec5SDimitry Andric bool parseRSectionDirective(StringRef Section);
3740b57cec5SDimitry Andric bool parseSSectionDirective(StringRef Section, unsigned Type);
3750b57cec5SDimitry Andric
3760b57cec5SDimitry Andric bool parseSetAtDirective();
3770b57cec5SDimitry Andric bool parseSetNoAtDirective();
3780b57cec5SDimitry Andric bool parseSetMacroDirective();
3790b57cec5SDimitry Andric bool parseSetNoMacroDirective();
3800b57cec5SDimitry Andric bool parseSetMsaDirective();
3810b57cec5SDimitry Andric bool parseSetNoMsaDirective();
3820b57cec5SDimitry Andric bool parseSetNoDspDirective();
3835ffd83dbSDimitry Andric bool parseSetNoMips3DDirective();
3840b57cec5SDimitry Andric bool parseSetReorderDirective();
3850b57cec5SDimitry Andric bool parseSetNoReorderDirective();
3860b57cec5SDimitry Andric bool parseSetMips16Directive();
3870b57cec5SDimitry Andric bool parseSetNoMips16Directive();
3880b57cec5SDimitry Andric bool parseSetFpDirective();
3890b57cec5SDimitry Andric bool parseSetOddSPRegDirective();
3900b57cec5SDimitry Andric bool parseSetNoOddSPRegDirective();
3910b57cec5SDimitry Andric bool parseSetPopDirective();
3920b57cec5SDimitry Andric bool parseSetPushDirective();
3930b57cec5SDimitry Andric bool parseSetSoftFloatDirective();
3940b57cec5SDimitry Andric bool parseSetHardFloatDirective();
3950b57cec5SDimitry Andric bool parseSetMtDirective();
3960b57cec5SDimitry Andric bool parseSetNoMtDirective();
3970b57cec5SDimitry Andric bool parseSetNoCRCDirective();
3980b57cec5SDimitry Andric bool parseSetNoVirtDirective();
3990b57cec5SDimitry Andric bool parseSetNoGINVDirective();
4000b57cec5SDimitry Andric
4010b57cec5SDimitry Andric bool parseSetAssignment();
4020b57cec5SDimitry Andric
4030b57cec5SDimitry Andric bool parseDirectiveGpWord();
4040b57cec5SDimitry Andric bool parseDirectiveGpDWord();
4050b57cec5SDimitry Andric bool parseDirectiveDtpRelWord();
4060b57cec5SDimitry Andric bool parseDirectiveDtpRelDWord();
4070b57cec5SDimitry Andric bool parseDirectiveTpRelWord();
4080b57cec5SDimitry Andric bool parseDirectiveTpRelDWord();
4090b57cec5SDimitry Andric bool parseDirectiveModule();
4100b57cec5SDimitry Andric bool parseDirectiveModuleFP();
4110b57cec5SDimitry Andric bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
4120b57cec5SDimitry Andric StringRef Directive);
4130b57cec5SDimitry Andric
4140b57cec5SDimitry Andric bool parseInternalDirectiveReallowModule();
4150b57cec5SDimitry Andric
4160b57cec5SDimitry Andric bool eatComma(StringRef ErrorStr);
4170b57cec5SDimitry Andric
4180b57cec5SDimitry Andric int matchCPURegisterName(StringRef Symbol);
4190b57cec5SDimitry Andric
4200b57cec5SDimitry Andric int matchHWRegsRegisterName(StringRef Symbol);
4210b57cec5SDimitry Andric
4220b57cec5SDimitry Andric int matchFPURegisterName(StringRef Name);
4230b57cec5SDimitry Andric
4240b57cec5SDimitry Andric int matchFCCRegisterName(StringRef Name);
4250b57cec5SDimitry Andric
4260b57cec5SDimitry Andric int matchACRegisterName(StringRef Name);
4270b57cec5SDimitry Andric
4280b57cec5SDimitry Andric int matchMSA128RegisterName(StringRef Name);
4290b57cec5SDimitry Andric
4300b57cec5SDimitry Andric int matchMSA128CtrlRegisterName(StringRef Name);
4310b57cec5SDimitry Andric
4320b57cec5SDimitry Andric unsigned getReg(int RC, int RegNo);
4330b57cec5SDimitry Andric
4340b57cec5SDimitry Andric /// Returns the internal register number for the current AT. Also checks if
4350b57cec5SDimitry Andric /// the current AT is unavailable (set to $0) and gives an error if it is.
4360b57cec5SDimitry Andric /// This should be used in pseudo-instruction expansions which need AT.
4370b57cec5SDimitry Andric unsigned getATReg(SMLoc Loc);
4380b57cec5SDimitry Andric
4390b57cec5SDimitry Andric bool canUseATReg();
4400b57cec5SDimitry Andric
4410b57cec5SDimitry Andric bool processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4420b57cec5SDimitry Andric const MCSubtargetInfo *STI);
4430b57cec5SDimitry Andric
4440b57cec5SDimitry Andric // Helper function that checks if the value of a vector index is within the
4450b57cec5SDimitry Andric // boundaries of accepted values for each RegisterKind
4460b57cec5SDimitry Andric // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
4470b57cec5SDimitry Andric bool validateMSAIndex(int Val, int RegKind);
4480b57cec5SDimitry Andric
4490b57cec5SDimitry Andric // Selects a new architecture by updating the FeatureBits with the necessary
4500b57cec5SDimitry Andric // info including implied dependencies.
4510b57cec5SDimitry Andric // Internally, it clears all the feature bits related to *any* architecture
4520b57cec5SDimitry Andric // and selects the new one using the ToggleFeature functionality of the
4530b57cec5SDimitry Andric // MCSubtargetInfo object that handles implied dependencies. The reason we
4540b57cec5SDimitry Andric // clear all the arch related bits manually is because ToggleFeature only
4550b57cec5SDimitry Andric // clears the features that imply the feature being cleared and not the
4560b57cec5SDimitry Andric // features implied by the feature being cleared. This is easier to see
4570b57cec5SDimitry Andric // with an example:
4580b57cec5SDimitry Andric // --------------------------------------------------
4590b57cec5SDimitry Andric // | Feature | Implies |
4600b57cec5SDimitry Andric // | -------------------------------------------------|
4610b57cec5SDimitry Andric // | FeatureMips1 | None |
4620b57cec5SDimitry Andric // | FeatureMips2 | FeatureMips1 |
4630b57cec5SDimitry Andric // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
4640b57cec5SDimitry Andric // | FeatureMips4 | FeatureMips3 |
4650b57cec5SDimitry Andric // | ... | |
4660b57cec5SDimitry Andric // --------------------------------------------------
4670b57cec5SDimitry Andric //
4680b57cec5SDimitry Andric // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
4690b57cec5SDimitry Andric // FeatureMipsGP64 | FeatureMips1)
4700b57cec5SDimitry Andric // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
selectArch(StringRef ArchFeature)4710b57cec5SDimitry Andric void selectArch(StringRef ArchFeature) {
4720b57cec5SDimitry Andric MCSubtargetInfo &STI = copySTI();
4730b57cec5SDimitry Andric FeatureBitset FeatureBits = STI.getFeatureBits();
4740b57cec5SDimitry Andric FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
4750b57cec5SDimitry Andric STI.setFeatureBits(FeatureBits);
4760b57cec5SDimitry Andric setAvailableFeatures(
4770b57cec5SDimitry Andric ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
4780b57cec5SDimitry Andric AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
4790b57cec5SDimitry Andric }
4800b57cec5SDimitry Andric
setFeatureBits(uint64_t Feature,StringRef FeatureString)4810b57cec5SDimitry Andric void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
48206c3fb27SDimitry Andric if (!(getSTI().hasFeature(Feature))) {
4830b57cec5SDimitry Andric MCSubtargetInfo &STI = copySTI();
4840b57cec5SDimitry Andric setAvailableFeatures(
4850b57cec5SDimitry Andric ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
4860b57cec5SDimitry Andric AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
4870b57cec5SDimitry Andric }
4880b57cec5SDimitry Andric }
4890b57cec5SDimitry Andric
clearFeatureBits(uint64_t Feature,StringRef FeatureString)4900b57cec5SDimitry Andric void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
49106c3fb27SDimitry Andric if (getSTI().hasFeature(Feature)) {
4920b57cec5SDimitry Andric MCSubtargetInfo &STI = copySTI();
4930b57cec5SDimitry Andric setAvailableFeatures(
4940b57cec5SDimitry Andric ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
4950b57cec5SDimitry Andric AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
4960b57cec5SDimitry Andric }
4970b57cec5SDimitry Andric }
4980b57cec5SDimitry Andric
setModuleFeatureBits(uint64_t Feature,StringRef FeatureString)4990b57cec5SDimitry Andric void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
5000b57cec5SDimitry Andric setFeatureBits(Feature, FeatureString);
5010b57cec5SDimitry Andric AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
5020b57cec5SDimitry Andric }
5030b57cec5SDimitry Andric
clearModuleFeatureBits(uint64_t Feature,StringRef FeatureString)5040b57cec5SDimitry Andric void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
5050b57cec5SDimitry Andric clearFeatureBits(Feature, FeatureString);
5060b57cec5SDimitry Andric AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
5070b57cec5SDimitry Andric }
5080b57cec5SDimitry Andric
5090b57cec5SDimitry Andric public:
5100b57cec5SDimitry Andric enum MipsMatchResultTy {
5110b57cec5SDimitry Andric Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY,
5120b57cec5SDimitry Andric Match_RequiresDifferentOperands,
5130b57cec5SDimitry Andric Match_RequiresNoZeroRegister,
5140b57cec5SDimitry Andric Match_RequiresSameSrcAndDst,
5150b57cec5SDimitry Andric Match_NoFCCRegisterForCurrentISA,
5160b57cec5SDimitry Andric Match_NonZeroOperandForSync,
5170b57cec5SDimitry Andric Match_NonZeroOperandForMTCX,
5180b57cec5SDimitry Andric Match_RequiresPosSizeRange0_32,
5190b57cec5SDimitry Andric Match_RequiresPosSizeRange33_64,
5200b57cec5SDimitry Andric Match_RequiresPosSizeUImm6,
5210b57cec5SDimitry Andric #define GET_OPERAND_DIAGNOSTIC_TYPES
5220b57cec5SDimitry Andric #include "MipsGenAsmMatcher.inc"
5230b57cec5SDimitry Andric #undef GET_OPERAND_DIAGNOSTIC_TYPES
5240b57cec5SDimitry Andric };
5250b57cec5SDimitry Andric
MipsAsmParser(const MCSubtargetInfo & sti,MCAsmParser & parser,const MCInstrInfo & MII,const MCTargetOptions & Options)5260b57cec5SDimitry Andric MipsAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,
5270b57cec5SDimitry Andric const MCInstrInfo &MII, const MCTargetOptions &Options)
5280b57cec5SDimitry Andric : MCTargetAsmParser(Options, sti, MII),
5290b57cec5SDimitry Andric ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
5300b57cec5SDimitry Andric sti.getCPU(), Options)) {
5310b57cec5SDimitry Andric MCAsmParserExtension::Initialize(parser);
5320b57cec5SDimitry Andric
5330b57cec5SDimitry Andric parser.addAliasForDirective(".asciiz", ".asciz");
5340b57cec5SDimitry Andric parser.addAliasForDirective(".hword", ".2byte");
5350b57cec5SDimitry Andric parser.addAliasForDirective(".word", ".4byte");
5360b57cec5SDimitry Andric parser.addAliasForDirective(".dword", ".8byte");
5370b57cec5SDimitry Andric
5380b57cec5SDimitry Andric // Initialize the set of available features.
5390b57cec5SDimitry Andric setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
5400b57cec5SDimitry Andric
5410b57cec5SDimitry Andric // Remember the initial assembler options. The user can not modify these.
5420b57cec5SDimitry Andric AssemblerOptions.push_back(
5438bcb0991SDimitry Andric std::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
5440b57cec5SDimitry Andric
5450b57cec5SDimitry Andric // Create an assembler options environment for the user to modify.
5460b57cec5SDimitry Andric AssemblerOptions.push_back(
5478bcb0991SDimitry Andric std::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
5480b57cec5SDimitry Andric
5490b57cec5SDimitry Andric getTargetStreamer().updateABIInfo(*this);
5500b57cec5SDimitry Andric
5510b57cec5SDimitry Andric if (!isABI_O32() && !useOddSPReg() != 0)
5520b57cec5SDimitry Andric report_fatal_error("-mno-odd-spreg requires the O32 ABI");
5530b57cec5SDimitry Andric
5540b57cec5SDimitry Andric CurrentFn = nullptr;
5550b57cec5SDimitry Andric
5564c2d3b02SDimitry Andric CurForbiddenSlotAttr = false;
5570b57cec5SDimitry Andric IsPicEnabled = getContext().getObjectFileInfo()->isPositionIndependent();
5580b57cec5SDimitry Andric
5590b57cec5SDimitry Andric IsCpRestoreSet = false;
5600b57cec5SDimitry Andric CpRestoreOffset = -1;
5610b57cec5SDimitry Andric GPReg = ABI.GetGlobalPtr();
5620b57cec5SDimitry Andric
5630b57cec5SDimitry Andric const Triple &TheTriple = sti.getTargetTriple();
5640b57cec5SDimitry Andric IsLittleEndian = TheTriple.isLittleEndian();
5650b57cec5SDimitry Andric
5660b57cec5SDimitry Andric if (getSTI().getCPU() == "mips64r6" && inMicroMipsMode())
5670b57cec5SDimitry Andric report_fatal_error("microMIPS64R6 is not supported", false);
5680b57cec5SDimitry Andric
5690b57cec5SDimitry Andric if (!isABI_O32() && inMicroMipsMode())
5700b57cec5SDimitry Andric report_fatal_error("microMIPS64 is not supported", false);
5710b57cec5SDimitry Andric }
5720b57cec5SDimitry Andric
5730b57cec5SDimitry Andric /// True if all of $fcc0 - $fcc7 exist for the current ISA.
hasEightFccRegisters() const5740b57cec5SDimitry Andric bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
5750b57cec5SDimitry Andric
isGP64bit() const5760b57cec5SDimitry Andric bool isGP64bit() const {
57706c3fb27SDimitry Andric return getSTI().hasFeature(Mips::FeatureGP64Bit);
5780b57cec5SDimitry Andric }
5790b57cec5SDimitry Andric
isFP64bit() const5800b57cec5SDimitry Andric bool isFP64bit() const {
58106c3fb27SDimitry Andric return getSTI().hasFeature(Mips::FeatureFP64Bit);
5820b57cec5SDimitry Andric }
5830b57cec5SDimitry Andric
isJalrRelocAvailable(const MCExpr * JalExpr)584480093f4SDimitry Andric bool isJalrRelocAvailable(const MCExpr *JalExpr) {
585480093f4SDimitry Andric if (!EmitJalrReloc)
586480093f4SDimitry Andric return false;
587480093f4SDimitry Andric MCValue Res;
588480093f4SDimitry Andric if (!JalExpr->evaluateAsRelocatable(Res, nullptr, nullptr))
589480093f4SDimitry Andric return false;
590480093f4SDimitry Andric if (Res.getSymB() != nullptr)
591480093f4SDimitry Andric return false;
592480093f4SDimitry Andric if (Res.getConstant() != 0)
593480093f4SDimitry Andric return ABI.IsN32() || ABI.IsN64();
594480093f4SDimitry Andric return true;
595480093f4SDimitry Andric }
596480093f4SDimitry Andric
getABI() const5970b57cec5SDimitry Andric const MipsABIInfo &getABI() const { return ABI; }
isABI_N32() const5980b57cec5SDimitry Andric bool isABI_N32() const { return ABI.IsN32(); }
isABI_N64() const5990b57cec5SDimitry Andric bool isABI_N64() const { return ABI.IsN64(); }
isABI_O32() const6000b57cec5SDimitry Andric bool isABI_O32() const { return ABI.IsO32(); }
isABI_FPXX() const6010b57cec5SDimitry Andric bool isABI_FPXX() const {
60206c3fb27SDimitry Andric return getSTI().hasFeature(Mips::FeatureFPXX);
6030b57cec5SDimitry Andric }
6040b57cec5SDimitry Andric
useOddSPReg() const6050b57cec5SDimitry Andric bool useOddSPReg() const {
60606c3fb27SDimitry Andric return !(getSTI().hasFeature(Mips::FeatureNoOddSPReg));
6070b57cec5SDimitry Andric }
6080b57cec5SDimitry Andric
inMicroMipsMode() const6090b57cec5SDimitry Andric bool inMicroMipsMode() const {
61006c3fb27SDimitry Andric return getSTI().hasFeature(Mips::FeatureMicroMips);
6110b57cec5SDimitry Andric }
6120b57cec5SDimitry Andric
hasMips1() const6130b57cec5SDimitry Andric bool hasMips1() const {
61406c3fb27SDimitry Andric return getSTI().hasFeature(Mips::FeatureMips1);
6150b57cec5SDimitry Andric }
6160b57cec5SDimitry Andric
hasMips2() const6170b57cec5SDimitry Andric bool hasMips2() const {
61806c3fb27SDimitry Andric return getSTI().hasFeature(Mips::FeatureMips2);
6190b57cec5SDimitry Andric }
6200b57cec5SDimitry Andric
hasMips3() const6210b57cec5SDimitry Andric bool hasMips3() const {
62206c3fb27SDimitry Andric return getSTI().hasFeature(Mips::FeatureMips3);
6230b57cec5SDimitry Andric }
6240b57cec5SDimitry Andric
hasMips4() const6250b57cec5SDimitry Andric bool hasMips4() const {
62606c3fb27SDimitry Andric return getSTI().hasFeature(Mips::FeatureMips4);
6270b57cec5SDimitry Andric }
6280b57cec5SDimitry Andric
hasMips5() const6290b57cec5SDimitry Andric bool hasMips5() const {
63006c3fb27SDimitry Andric return getSTI().hasFeature(Mips::FeatureMips5);
6310b57cec5SDimitry Andric }
6320b57cec5SDimitry Andric
hasMips32() const6330b57cec5SDimitry Andric bool hasMips32() const {
63406c3fb27SDimitry Andric return getSTI().hasFeature(Mips::FeatureMips32);
6350b57cec5SDimitry Andric }
6360b57cec5SDimitry Andric
hasMips64() const6370b57cec5SDimitry Andric bool hasMips64() const {
63806c3fb27SDimitry Andric return getSTI().hasFeature(Mips::FeatureMips64);
6390b57cec5SDimitry Andric }
6400b57cec5SDimitry Andric
hasMips32r2() const6410b57cec5SDimitry Andric bool hasMips32r2() const {
64206c3fb27SDimitry Andric return getSTI().hasFeature(Mips::FeatureMips32r2);
6430b57cec5SDimitry Andric }
6440b57cec5SDimitry Andric
hasMips64r2() const6450b57cec5SDimitry Andric bool hasMips64r2() const {
64606c3fb27SDimitry Andric return getSTI().hasFeature(Mips::FeatureMips64r2);
6470b57cec5SDimitry Andric }
6480b57cec5SDimitry Andric
hasMips32r3() const6490b57cec5SDimitry Andric bool hasMips32r3() const {
65006c3fb27SDimitry Andric return (getSTI().hasFeature(Mips::FeatureMips32r3));
6510b57cec5SDimitry Andric }
6520b57cec5SDimitry Andric
hasMips64r3() const6530b57cec5SDimitry Andric bool hasMips64r3() const {
65406c3fb27SDimitry Andric return (getSTI().hasFeature(Mips::FeatureMips64r3));
6550b57cec5SDimitry Andric }
6560b57cec5SDimitry Andric
hasMips32r5() const6570b57cec5SDimitry Andric bool hasMips32r5() const {
65806c3fb27SDimitry Andric return (getSTI().hasFeature(Mips::FeatureMips32r5));
6590b57cec5SDimitry Andric }
6600b57cec5SDimitry Andric
hasMips64r5() const6610b57cec5SDimitry Andric bool hasMips64r5() const {
66206c3fb27SDimitry Andric return (getSTI().hasFeature(Mips::FeatureMips64r5));
6630b57cec5SDimitry Andric }
6640b57cec5SDimitry Andric
hasMips32r6() const6650b57cec5SDimitry Andric bool hasMips32r6() const {
66606c3fb27SDimitry Andric return getSTI().hasFeature(Mips::FeatureMips32r6);
6670b57cec5SDimitry Andric }
6680b57cec5SDimitry Andric
hasMips64r6() const6690b57cec5SDimitry Andric bool hasMips64r6() const {
67006c3fb27SDimitry Andric return getSTI().hasFeature(Mips::FeatureMips64r6);
6710b57cec5SDimitry Andric }
6720b57cec5SDimitry Andric
hasDSP() const6730b57cec5SDimitry Andric bool hasDSP() const {
67406c3fb27SDimitry Andric return getSTI().hasFeature(Mips::FeatureDSP);
6750b57cec5SDimitry Andric }
6760b57cec5SDimitry Andric
hasDSPR2() const6770b57cec5SDimitry Andric bool hasDSPR2() const {
67806c3fb27SDimitry Andric return getSTI().hasFeature(Mips::FeatureDSPR2);
6790b57cec5SDimitry Andric }
6800b57cec5SDimitry Andric
hasDSPR3() const6810b57cec5SDimitry Andric bool hasDSPR3() const {
68206c3fb27SDimitry Andric return getSTI().hasFeature(Mips::FeatureDSPR3);
6830b57cec5SDimitry Andric }
6840b57cec5SDimitry Andric
hasMSA() const6850b57cec5SDimitry Andric bool hasMSA() const {
68606c3fb27SDimitry Andric return getSTI().hasFeature(Mips::FeatureMSA);
6870b57cec5SDimitry Andric }
6880b57cec5SDimitry Andric
hasCnMips() const6890b57cec5SDimitry Andric bool hasCnMips() const {
69006c3fb27SDimitry Andric return (getSTI().hasFeature(Mips::FeatureCnMips));
6910b57cec5SDimitry Andric }
6920b57cec5SDimitry Andric
hasCnMipsP() const6930b57cec5SDimitry Andric bool hasCnMipsP() const {
69406c3fb27SDimitry Andric return (getSTI().hasFeature(Mips::FeatureCnMipsP));
6950b57cec5SDimitry Andric }
6960b57cec5SDimitry Andric
inPicMode()6970b57cec5SDimitry Andric bool inPicMode() {
6980b57cec5SDimitry Andric return IsPicEnabled;
6990b57cec5SDimitry Andric }
7000b57cec5SDimitry Andric
inMips16Mode() const7010b57cec5SDimitry Andric bool inMips16Mode() const {
70206c3fb27SDimitry Andric return getSTI().hasFeature(Mips::FeatureMips16);
7030b57cec5SDimitry Andric }
7040b57cec5SDimitry Andric
useTraps() const7050b57cec5SDimitry Andric bool useTraps() const {
70606c3fb27SDimitry Andric return getSTI().hasFeature(Mips::FeatureUseTCCInDIV);
7070b57cec5SDimitry Andric }
7080b57cec5SDimitry Andric
useSoftFloat() const7090b57cec5SDimitry Andric bool useSoftFloat() const {
71006c3fb27SDimitry Andric return getSTI().hasFeature(Mips::FeatureSoftFloat);
7110b57cec5SDimitry Andric }
hasMT() const7120b57cec5SDimitry Andric bool hasMT() const {
71306c3fb27SDimitry Andric return getSTI().hasFeature(Mips::FeatureMT);
7140b57cec5SDimitry Andric }
7150b57cec5SDimitry Andric
hasCRC() const7160b57cec5SDimitry Andric bool hasCRC() const {
71706c3fb27SDimitry Andric return getSTI().hasFeature(Mips::FeatureCRC);
7180b57cec5SDimitry Andric }
7190b57cec5SDimitry Andric
hasVirt() const7200b57cec5SDimitry Andric bool hasVirt() const {
72106c3fb27SDimitry Andric return getSTI().hasFeature(Mips::FeatureVirt);
7220b57cec5SDimitry Andric }
7230b57cec5SDimitry Andric
hasGINV() const7240b57cec5SDimitry Andric bool hasGINV() const {
72506c3fb27SDimitry Andric return getSTI().hasFeature(Mips::FeatureGINV);
7260b57cec5SDimitry Andric }
7270b57cec5SDimitry Andric
hasForbiddenSlot(const MCInstrDesc & MCID) const7284c2d3b02SDimitry Andric bool hasForbiddenSlot(const MCInstrDesc &MCID) const {
7294c2d3b02SDimitry Andric return !inMicroMipsMode() && (MCID.TSFlags & MipsII::HasForbiddenSlot);
7304c2d3b02SDimitry Andric }
7314c2d3b02SDimitry Andric
SafeInForbiddenSlot(const MCInstrDesc & MCID) const7324c2d3b02SDimitry Andric bool SafeInForbiddenSlot(const MCInstrDesc &MCID) const {
7334c2d3b02SDimitry Andric return !(MCID.TSFlags & MipsII::IsCTI);
7344c2d3b02SDimitry Andric }
7354c2d3b02SDimitry Andric
7364c2d3b02SDimitry Andric void onEndOfFile() override;
7374c2d3b02SDimitry Andric
7380b57cec5SDimitry Andric /// Warn if RegIndex is the same as the current AT.
7390b57cec5SDimitry Andric void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
7400b57cec5SDimitry Andric
7410b57cec5SDimitry Andric void warnIfNoMacro(SMLoc Loc);
7420b57cec5SDimitry Andric
isLittle() const7430b57cec5SDimitry Andric bool isLittle() const { return IsLittleEndian; }
7440b57cec5SDimitry Andric
createTargetUnaryExpr(const MCExpr * E,AsmToken::TokenKind OperatorToken,MCContext & Ctx)7450b57cec5SDimitry Andric const MCExpr *createTargetUnaryExpr(const MCExpr *E,
7460b57cec5SDimitry Andric AsmToken::TokenKind OperatorToken,
7470b57cec5SDimitry Andric MCContext &Ctx) override {
7480b57cec5SDimitry Andric switch(OperatorToken) {
7490b57cec5SDimitry Andric default:
7500b57cec5SDimitry Andric llvm_unreachable("Unknown token");
7510b57cec5SDimitry Andric return nullptr;
7520b57cec5SDimitry Andric case AsmToken::PercentCall16:
7530b57cec5SDimitry Andric return MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, E, Ctx);
7540b57cec5SDimitry Andric case AsmToken::PercentCall_Hi:
7550b57cec5SDimitry Andric return MipsMCExpr::create(MipsMCExpr::MEK_CALL_HI16, E, Ctx);
7560b57cec5SDimitry Andric case AsmToken::PercentCall_Lo:
7570b57cec5SDimitry Andric return MipsMCExpr::create(MipsMCExpr::MEK_CALL_LO16, E, Ctx);
7580b57cec5SDimitry Andric case AsmToken::PercentDtprel_Hi:
7590b57cec5SDimitry Andric return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_HI, E, Ctx);
7600b57cec5SDimitry Andric case AsmToken::PercentDtprel_Lo:
7610b57cec5SDimitry Andric return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_LO, E, Ctx);
7620b57cec5SDimitry Andric case AsmToken::PercentGot:
7630b57cec5SDimitry Andric return MipsMCExpr::create(MipsMCExpr::MEK_GOT, E, Ctx);
7640b57cec5SDimitry Andric case AsmToken::PercentGot_Disp:
7650b57cec5SDimitry Andric return MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, E, Ctx);
7660b57cec5SDimitry Andric case AsmToken::PercentGot_Hi:
7670b57cec5SDimitry Andric return MipsMCExpr::create(MipsMCExpr::MEK_GOT_HI16, E, Ctx);
7680b57cec5SDimitry Andric case AsmToken::PercentGot_Lo:
7690b57cec5SDimitry Andric return MipsMCExpr::create(MipsMCExpr::MEK_GOT_LO16, E, Ctx);
7700b57cec5SDimitry Andric case AsmToken::PercentGot_Ofst:
7710b57cec5SDimitry Andric return MipsMCExpr::create(MipsMCExpr::MEK_GOT_OFST, E, Ctx);
7720b57cec5SDimitry Andric case AsmToken::PercentGot_Page:
7730b57cec5SDimitry Andric return MipsMCExpr::create(MipsMCExpr::MEK_GOT_PAGE, E, Ctx);
7740b57cec5SDimitry Andric case AsmToken::PercentGottprel:
7750b57cec5SDimitry Andric return MipsMCExpr::create(MipsMCExpr::MEK_GOTTPREL, E, Ctx);
7760b57cec5SDimitry Andric case AsmToken::PercentGp_Rel:
7770b57cec5SDimitry Andric return MipsMCExpr::create(MipsMCExpr::MEK_GPREL, E, Ctx);
7780b57cec5SDimitry Andric case AsmToken::PercentHi:
7790b57cec5SDimitry Andric return MipsMCExpr::create(MipsMCExpr::MEK_HI, E, Ctx);
7800b57cec5SDimitry Andric case AsmToken::PercentHigher:
7810b57cec5SDimitry Andric return MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, E, Ctx);
7820b57cec5SDimitry Andric case AsmToken::PercentHighest:
7830b57cec5SDimitry Andric return MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, E, Ctx);
7840b57cec5SDimitry Andric case AsmToken::PercentLo:
7850b57cec5SDimitry Andric return MipsMCExpr::create(MipsMCExpr::MEK_LO, E, Ctx);
7860b57cec5SDimitry Andric case AsmToken::PercentNeg:
7870b57cec5SDimitry Andric return MipsMCExpr::create(MipsMCExpr::MEK_NEG, E, Ctx);
7880b57cec5SDimitry Andric case AsmToken::PercentPcrel_Hi:
7890b57cec5SDimitry Andric return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_HI16, E, Ctx);
7900b57cec5SDimitry Andric case AsmToken::PercentPcrel_Lo:
7910b57cec5SDimitry Andric return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_LO16, E, Ctx);
7920b57cec5SDimitry Andric case AsmToken::PercentTlsgd:
7930b57cec5SDimitry Andric return MipsMCExpr::create(MipsMCExpr::MEK_TLSGD, E, Ctx);
7940b57cec5SDimitry Andric case AsmToken::PercentTlsldm:
7950b57cec5SDimitry Andric return MipsMCExpr::create(MipsMCExpr::MEK_TLSLDM, E, Ctx);
7960b57cec5SDimitry Andric case AsmToken::PercentTprel_Hi:
7970b57cec5SDimitry Andric return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_HI, E, Ctx);
7980b57cec5SDimitry Andric case AsmToken::PercentTprel_Lo:
7990b57cec5SDimitry Andric return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_LO, E, Ctx);
8000b57cec5SDimitry Andric }
8010b57cec5SDimitry Andric }
802bdd1243dSDimitry Andric
803bdd1243dSDimitry Andric bool areEqualRegs(const MCParsedAsmOperand &Op1,
804bdd1243dSDimitry Andric const MCParsedAsmOperand &Op2) const override;
8050b57cec5SDimitry Andric };
8060b57cec5SDimitry Andric
8070b57cec5SDimitry Andric /// MipsOperand - Instances of this class represent a parsed Mips machine
8080b57cec5SDimitry Andric /// instruction.
8090b57cec5SDimitry Andric class MipsOperand : public MCParsedAsmOperand {
8100b57cec5SDimitry Andric public:
8110b57cec5SDimitry Andric /// Broad categories of register classes
8120b57cec5SDimitry Andric /// The exact class is finalized by the render method.
8130b57cec5SDimitry Andric enum RegKind {
8140b57cec5SDimitry Andric RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
8150b57cec5SDimitry Andric RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
8160b57cec5SDimitry Andric /// isFP64bit())
8170b57cec5SDimitry Andric RegKind_FCC = 4, /// FCC
8180b57cec5SDimitry Andric RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
8190b57cec5SDimitry Andric RegKind_MSACtrl = 16, /// MSA control registers
8200b57cec5SDimitry Andric RegKind_COP2 = 32, /// COP2
8210b57cec5SDimitry Andric RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
8220b57cec5SDimitry Andric /// context).
8230b57cec5SDimitry Andric RegKind_CCR = 128, /// CCR
8240b57cec5SDimitry Andric RegKind_HWRegs = 256, /// HWRegs
8250b57cec5SDimitry Andric RegKind_COP3 = 512, /// COP3
8260b57cec5SDimitry Andric RegKind_COP0 = 1024, /// COP0
8270b57cec5SDimitry Andric /// Potentially any (e.g. $1)
8280b57cec5SDimitry Andric RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
8290b57cec5SDimitry Andric RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
8300b57cec5SDimitry Andric RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
8310b57cec5SDimitry Andric };
8320b57cec5SDimitry Andric
8330b57cec5SDimitry Andric private:
8340b57cec5SDimitry Andric enum KindTy {
8350b57cec5SDimitry Andric k_Immediate, /// An immediate (possibly involving symbol references)
8360b57cec5SDimitry Andric k_Memory, /// Base + Offset Memory Address
8370b57cec5SDimitry Andric k_RegisterIndex, /// A register index in one or more RegKind.
8380b57cec5SDimitry Andric k_Token, /// A simple token
8390b57cec5SDimitry Andric k_RegList, /// A physical register list
8400b57cec5SDimitry Andric } Kind;
8410b57cec5SDimitry Andric
8420b57cec5SDimitry Andric public:
MipsOperand(KindTy K,MipsAsmParser & Parser)84304eeddc0SDimitry Andric MipsOperand(KindTy K, MipsAsmParser &Parser) : Kind(K), AsmParser(Parser) {}
8440b57cec5SDimitry Andric
~MipsOperand()8450b57cec5SDimitry Andric ~MipsOperand() override {
8460b57cec5SDimitry Andric switch (Kind) {
8470b57cec5SDimitry Andric case k_Memory:
8480b57cec5SDimitry Andric delete Mem.Base;
8490b57cec5SDimitry Andric break;
8500b57cec5SDimitry Andric case k_RegList:
8510b57cec5SDimitry Andric delete RegList.List;
8520b57cec5SDimitry Andric break;
8530b57cec5SDimitry Andric case k_Immediate:
8540b57cec5SDimitry Andric case k_RegisterIndex:
8550b57cec5SDimitry Andric case k_Token:
8560b57cec5SDimitry Andric break;
8570b57cec5SDimitry Andric }
8580b57cec5SDimitry Andric }
8590b57cec5SDimitry Andric
8600b57cec5SDimitry Andric private:
8610b57cec5SDimitry Andric /// For diagnostics, and checking the assembler temporary
8620b57cec5SDimitry Andric MipsAsmParser &AsmParser;
8630b57cec5SDimitry Andric
8640b57cec5SDimitry Andric struct Token {
8650b57cec5SDimitry Andric const char *Data;
8660b57cec5SDimitry Andric unsigned Length;
8670b57cec5SDimitry Andric };
8680b57cec5SDimitry Andric
8690b57cec5SDimitry Andric struct RegIdxOp {
8700b57cec5SDimitry Andric unsigned Index; /// Index into the register class
8710b57cec5SDimitry Andric RegKind Kind; /// Bitfield of the kinds it could possibly be
8720b57cec5SDimitry Andric struct Token Tok; /// The input token this operand originated from.
8730b57cec5SDimitry Andric const MCRegisterInfo *RegInfo;
8740b57cec5SDimitry Andric };
8750b57cec5SDimitry Andric
8760b57cec5SDimitry Andric struct ImmOp {
8770b57cec5SDimitry Andric const MCExpr *Val;
8780b57cec5SDimitry Andric };
8790b57cec5SDimitry Andric
8800b57cec5SDimitry Andric struct MemOp {
8810b57cec5SDimitry Andric MipsOperand *Base;
8820b57cec5SDimitry Andric const MCExpr *Off;
8830b57cec5SDimitry Andric };
8840b57cec5SDimitry Andric
8850b57cec5SDimitry Andric struct RegListOp {
8860b57cec5SDimitry Andric SmallVector<unsigned, 10> *List;
8870b57cec5SDimitry Andric };
8880b57cec5SDimitry Andric
8890b57cec5SDimitry Andric union {
8900b57cec5SDimitry Andric struct Token Tok;
8910b57cec5SDimitry Andric struct RegIdxOp RegIdx;
8920b57cec5SDimitry Andric struct ImmOp Imm;
8930b57cec5SDimitry Andric struct MemOp Mem;
8940b57cec5SDimitry Andric struct RegListOp RegList;
8950b57cec5SDimitry Andric };
8960b57cec5SDimitry Andric
8970b57cec5SDimitry Andric SMLoc StartLoc, EndLoc;
8980b57cec5SDimitry Andric
8990b57cec5SDimitry Andric /// Internal constructor for register kinds
CreateReg(unsigned Index,StringRef Str,RegKind RegKind,const MCRegisterInfo * RegInfo,SMLoc S,SMLoc E,MipsAsmParser & Parser)9000b57cec5SDimitry Andric static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, StringRef Str,
9010b57cec5SDimitry Andric RegKind RegKind,
9020b57cec5SDimitry Andric const MCRegisterInfo *RegInfo,
9030b57cec5SDimitry Andric SMLoc S, SMLoc E,
9040b57cec5SDimitry Andric MipsAsmParser &Parser) {
9058bcb0991SDimitry Andric auto Op = std::make_unique<MipsOperand>(k_RegisterIndex, Parser);
9060b57cec5SDimitry Andric Op->RegIdx.Index = Index;
9070b57cec5SDimitry Andric Op->RegIdx.RegInfo = RegInfo;
9080b57cec5SDimitry Andric Op->RegIdx.Kind = RegKind;
9090b57cec5SDimitry Andric Op->RegIdx.Tok.Data = Str.data();
9100b57cec5SDimitry Andric Op->RegIdx.Tok.Length = Str.size();
9110b57cec5SDimitry Andric Op->StartLoc = S;
9120b57cec5SDimitry Andric Op->EndLoc = E;
9130b57cec5SDimitry Andric return Op;
9140b57cec5SDimitry Andric }
9150b57cec5SDimitry Andric
9160b57cec5SDimitry Andric public:
9170b57cec5SDimitry Andric /// Coerce the register to GPR32 and return the real register for the current
9180b57cec5SDimitry Andric /// target.
getGPR32Reg() const9190b57cec5SDimitry Andric unsigned getGPR32Reg() const {
9200b57cec5SDimitry Andric assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
9210b57cec5SDimitry Andric AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
9220b57cec5SDimitry Andric unsigned ClassID = Mips::GPR32RegClassID;
9230b57cec5SDimitry Andric return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
9240b57cec5SDimitry Andric }
9250b57cec5SDimitry Andric
9260b57cec5SDimitry Andric /// Coerce the register to GPR32 and return the real register for the current
9270b57cec5SDimitry Andric /// target.
getGPRMM16Reg() const9280b57cec5SDimitry Andric unsigned getGPRMM16Reg() const {
9290b57cec5SDimitry Andric assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
9300b57cec5SDimitry Andric unsigned ClassID = Mips::GPR32RegClassID;
9310b57cec5SDimitry Andric return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
9320b57cec5SDimitry Andric }
9330b57cec5SDimitry Andric
9340b57cec5SDimitry Andric /// Coerce the register to GPR64 and return the real register for the current
9350b57cec5SDimitry Andric /// target.
getGPR64Reg() const9360b57cec5SDimitry Andric unsigned getGPR64Reg() const {
9370b57cec5SDimitry Andric assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
9380b57cec5SDimitry Andric unsigned ClassID = Mips::GPR64RegClassID;
9390b57cec5SDimitry Andric return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
9400b57cec5SDimitry Andric }
9410b57cec5SDimitry Andric
9420b57cec5SDimitry Andric private:
9430b57cec5SDimitry Andric /// Coerce the register to AFGR64 and return the real register for the current
9440b57cec5SDimitry Andric /// target.
getAFGR64Reg() const9450b57cec5SDimitry Andric unsigned getAFGR64Reg() const {
9460b57cec5SDimitry Andric assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
9470b57cec5SDimitry Andric if (RegIdx.Index % 2 != 0)
9480b57cec5SDimitry Andric AsmParser.Warning(StartLoc, "Float register should be even.");
9490b57cec5SDimitry Andric return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
9500b57cec5SDimitry Andric .getRegister(RegIdx.Index / 2);
9510b57cec5SDimitry Andric }
9520b57cec5SDimitry Andric
9530b57cec5SDimitry Andric /// Coerce the register to FGR64 and return the real register for the current
9540b57cec5SDimitry Andric /// target.
getFGR64Reg() const9550b57cec5SDimitry Andric unsigned getFGR64Reg() const {
9560b57cec5SDimitry Andric assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
9570b57cec5SDimitry Andric return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
9580b57cec5SDimitry Andric .getRegister(RegIdx.Index);
9590b57cec5SDimitry Andric }
9600b57cec5SDimitry Andric
9610b57cec5SDimitry Andric /// Coerce the register to FGR32 and return the real register for the current
9620b57cec5SDimitry Andric /// target.
getFGR32Reg() const9630b57cec5SDimitry Andric unsigned getFGR32Reg() const {
9640b57cec5SDimitry Andric assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
9650b57cec5SDimitry Andric return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
9660b57cec5SDimitry Andric .getRegister(RegIdx.Index);
9670b57cec5SDimitry Andric }
9680b57cec5SDimitry Andric
9690b57cec5SDimitry Andric /// Coerce the register to FCC and return the real register for the current
9700b57cec5SDimitry Andric /// target.
getFCCReg() const9710b57cec5SDimitry Andric unsigned getFCCReg() const {
9720b57cec5SDimitry Andric assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
9730b57cec5SDimitry Andric return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
9740b57cec5SDimitry Andric .getRegister(RegIdx.Index);
9750b57cec5SDimitry Andric }
9760b57cec5SDimitry Andric
9770b57cec5SDimitry Andric /// Coerce the register to MSA128 and return the real register for the current
9780b57cec5SDimitry Andric /// target.
getMSA128Reg() const9790b57cec5SDimitry Andric unsigned getMSA128Reg() const {
9800b57cec5SDimitry Andric assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
9810b57cec5SDimitry Andric // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
9820b57cec5SDimitry Andric // identical
9830b57cec5SDimitry Andric unsigned ClassID = Mips::MSA128BRegClassID;
9840b57cec5SDimitry Andric return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
9850b57cec5SDimitry Andric }
9860b57cec5SDimitry Andric
9870b57cec5SDimitry Andric /// Coerce the register to MSACtrl and return the real register for the
9880b57cec5SDimitry Andric /// current target.
getMSACtrlReg() const9890b57cec5SDimitry Andric unsigned getMSACtrlReg() const {
9900b57cec5SDimitry Andric assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
9910b57cec5SDimitry Andric unsigned ClassID = Mips::MSACtrlRegClassID;
9920b57cec5SDimitry Andric return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
9930b57cec5SDimitry Andric }
9940b57cec5SDimitry Andric
9950b57cec5SDimitry Andric /// Coerce the register to COP0 and return the real register for the
9960b57cec5SDimitry Andric /// current target.
getCOP0Reg() const9970b57cec5SDimitry Andric unsigned getCOP0Reg() const {
9980b57cec5SDimitry Andric assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");
9990b57cec5SDimitry Andric unsigned ClassID = Mips::COP0RegClassID;
10000b57cec5SDimitry Andric return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
10010b57cec5SDimitry Andric }
10020b57cec5SDimitry Andric
10030b57cec5SDimitry Andric /// Coerce the register to COP2 and return the real register for the
10040b57cec5SDimitry Andric /// current target.
getCOP2Reg() const10050b57cec5SDimitry Andric unsigned getCOP2Reg() const {
10060b57cec5SDimitry Andric assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
10070b57cec5SDimitry Andric unsigned ClassID = Mips::COP2RegClassID;
10080b57cec5SDimitry Andric return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
10090b57cec5SDimitry Andric }
10100b57cec5SDimitry Andric
10110b57cec5SDimitry Andric /// Coerce the register to COP3 and return the real register for the
10120b57cec5SDimitry Andric /// current target.
getCOP3Reg() const10130b57cec5SDimitry Andric unsigned getCOP3Reg() const {
10140b57cec5SDimitry Andric assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
10150b57cec5SDimitry Andric unsigned ClassID = Mips::COP3RegClassID;
10160b57cec5SDimitry Andric return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
10170b57cec5SDimitry Andric }
10180b57cec5SDimitry Andric
10190b57cec5SDimitry Andric /// Coerce the register to ACC64DSP and return the real register for the
10200b57cec5SDimitry Andric /// current target.
getACC64DSPReg() const10210b57cec5SDimitry Andric unsigned getACC64DSPReg() const {
10220b57cec5SDimitry Andric assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
10230b57cec5SDimitry Andric unsigned ClassID = Mips::ACC64DSPRegClassID;
10240b57cec5SDimitry Andric return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
10250b57cec5SDimitry Andric }
10260b57cec5SDimitry Andric
10270b57cec5SDimitry Andric /// Coerce the register to HI32DSP and return the real register for the
10280b57cec5SDimitry Andric /// current target.
getHI32DSPReg() const10290b57cec5SDimitry Andric unsigned getHI32DSPReg() const {
10300b57cec5SDimitry Andric assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
10310b57cec5SDimitry Andric unsigned ClassID = Mips::HI32DSPRegClassID;
10320b57cec5SDimitry Andric return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
10330b57cec5SDimitry Andric }
10340b57cec5SDimitry Andric
10350b57cec5SDimitry Andric /// Coerce the register to LO32DSP and return the real register for the
10360b57cec5SDimitry Andric /// current target.
getLO32DSPReg() const10370b57cec5SDimitry Andric unsigned getLO32DSPReg() const {
10380b57cec5SDimitry Andric assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
10390b57cec5SDimitry Andric unsigned ClassID = Mips::LO32DSPRegClassID;
10400b57cec5SDimitry Andric return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
10410b57cec5SDimitry Andric }
10420b57cec5SDimitry Andric
10430b57cec5SDimitry Andric /// Coerce the register to CCR and return the real register for the
10440b57cec5SDimitry Andric /// current target.
getCCRReg() const10450b57cec5SDimitry Andric unsigned getCCRReg() const {
10460b57cec5SDimitry Andric assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
10470b57cec5SDimitry Andric unsigned ClassID = Mips::CCRRegClassID;
10480b57cec5SDimitry Andric return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
10490b57cec5SDimitry Andric }
10500b57cec5SDimitry Andric
10510b57cec5SDimitry Andric /// Coerce the register to HWRegs and return the real register for the
10520b57cec5SDimitry Andric /// current target.
getHWRegsReg() const10530b57cec5SDimitry Andric unsigned getHWRegsReg() const {
10540b57cec5SDimitry Andric assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
10550b57cec5SDimitry Andric unsigned ClassID = Mips::HWRegsRegClassID;
10560b57cec5SDimitry Andric return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
10570b57cec5SDimitry Andric }
10580b57cec5SDimitry Andric
10590b57cec5SDimitry Andric public:
addExpr(MCInst & Inst,const MCExpr * Expr) const10600b57cec5SDimitry Andric void addExpr(MCInst &Inst, const MCExpr *Expr) const {
10610b57cec5SDimitry Andric // Add as immediate when possible. Null MCExpr = 0.
10620b57cec5SDimitry Andric if (!Expr)
10630b57cec5SDimitry Andric Inst.addOperand(MCOperand::createImm(0));
10640b57cec5SDimitry Andric else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
10650b57cec5SDimitry Andric Inst.addOperand(MCOperand::createImm(CE->getValue()));
10660b57cec5SDimitry Andric else
10670b57cec5SDimitry Andric Inst.addOperand(MCOperand::createExpr(Expr));
10680b57cec5SDimitry Andric }
10690b57cec5SDimitry Andric
addRegOperands(MCInst & Inst,unsigned N) const10700b57cec5SDimitry Andric void addRegOperands(MCInst &Inst, unsigned N) const {
10710b57cec5SDimitry Andric llvm_unreachable("Use a custom parser instead");
10720b57cec5SDimitry Andric }
10730b57cec5SDimitry Andric
10740b57cec5SDimitry Andric /// Render the operand to an MCInst as a GPR32
10750b57cec5SDimitry Andric /// Asserts if the wrong number of operands are requested, or the operand
10760b57cec5SDimitry Andric /// is not a k_RegisterIndex compatible with RegKind_GPR
addGPR32ZeroAsmRegOperands(MCInst & Inst,unsigned N) const10770b57cec5SDimitry Andric void addGPR32ZeroAsmRegOperands(MCInst &Inst, unsigned N) const {
10780b57cec5SDimitry Andric assert(N == 1 && "Invalid number of operands!");
10790b57cec5SDimitry Andric Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
10800b57cec5SDimitry Andric }
10810b57cec5SDimitry Andric
addGPR32NonZeroAsmRegOperands(MCInst & Inst,unsigned N) const10820b57cec5SDimitry Andric void addGPR32NonZeroAsmRegOperands(MCInst &Inst, unsigned N) const {
10830b57cec5SDimitry Andric assert(N == 1 && "Invalid number of operands!");
10840b57cec5SDimitry Andric Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
10850b57cec5SDimitry Andric }
10860b57cec5SDimitry Andric
addGPR32AsmRegOperands(MCInst & Inst,unsigned N) const10870b57cec5SDimitry Andric void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
10880b57cec5SDimitry Andric assert(N == 1 && "Invalid number of operands!");
10890b57cec5SDimitry Andric Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
10900b57cec5SDimitry Andric }
10910b57cec5SDimitry Andric
addGPRMM16AsmRegOperands(MCInst & Inst,unsigned N) const10920b57cec5SDimitry Andric void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
10930b57cec5SDimitry Andric assert(N == 1 && "Invalid number of operands!");
10940b57cec5SDimitry Andric Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
10950b57cec5SDimitry Andric }
10960b57cec5SDimitry Andric
addGPRMM16AsmRegZeroOperands(MCInst & Inst,unsigned N) const10970b57cec5SDimitry Andric void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
10980b57cec5SDimitry Andric assert(N == 1 && "Invalid number of operands!");
10990b57cec5SDimitry Andric Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
11000b57cec5SDimitry Andric }
11010b57cec5SDimitry Andric
addGPRMM16AsmRegMovePOperands(MCInst & Inst,unsigned N) const11020b57cec5SDimitry Andric void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
11030b57cec5SDimitry Andric assert(N == 1 && "Invalid number of operands!");
11040b57cec5SDimitry Andric Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
11050b57cec5SDimitry Andric }
11060b57cec5SDimitry Andric
addGPRMM16AsmRegMovePPairFirstOperands(MCInst & Inst,unsigned N) const11070b57cec5SDimitry Andric void addGPRMM16AsmRegMovePPairFirstOperands(MCInst &Inst, unsigned N) const {
11080b57cec5SDimitry Andric assert(N == 1 && "Invalid number of operands!");
11090b57cec5SDimitry Andric Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
11100b57cec5SDimitry Andric }
11110b57cec5SDimitry Andric
addGPRMM16AsmRegMovePPairSecondOperands(MCInst & Inst,unsigned N) const11120b57cec5SDimitry Andric void addGPRMM16AsmRegMovePPairSecondOperands(MCInst &Inst,
11130b57cec5SDimitry Andric unsigned N) const {
11140b57cec5SDimitry Andric assert(N == 1 && "Invalid number of operands!");
11150b57cec5SDimitry Andric Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
11160b57cec5SDimitry Andric }
11170b57cec5SDimitry Andric
11180b57cec5SDimitry Andric /// Render the operand to an MCInst as a GPR64
11190b57cec5SDimitry Andric /// Asserts if the wrong number of operands are requested, or the operand
11200b57cec5SDimitry Andric /// is not a k_RegisterIndex compatible with RegKind_GPR
addGPR64AsmRegOperands(MCInst & Inst,unsigned N) const11210b57cec5SDimitry Andric void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
11220b57cec5SDimitry Andric assert(N == 1 && "Invalid number of operands!");
11230b57cec5SDimitry Andric Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
11240b57cec5SDimitry Andric }
11250b57cec5SDimitry Andric
addAFGR64AsmRegOperands(MCInst & Inst,unsigned N) const11260b57cec5SDimitry Andric void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
11270b57cec5SDimitry Andric assert(N == 1 && "Invalid number of operands!");
11280b57cec5SDimitry Andric Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
11290b57cec5SDimitry Andric }
11300b57cec5SDimitry Andric
addStrictlyAFGR64AsmRegOperands(MCInst & Inst,unsigned N) const11310b57cec5SDimitry Andric void addStrictlyAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
11320b57cec5SDimitry Andric assert(N == 1 && "Invalid number of operands!");
11330b57cec5SDimitry Andric Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
11340b57cec5SDimitry Andric }
11350b57cec5SDimitry Andric
addStrictlyFGR64AsmRegOperands(MCInst & Inst,unsigned N) const11360b57cec5SDimitry Andric void addStrictlyFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
11370b57cec5SDimitry Andric assert(N == 1 && "Invalid number of operands!");
11380b57cec5SDimitry Andric Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
11390b57cec5SDimitry Andric }
11400b57cec5SDimitry Andric
addFGR64AsmRegOperands(MCInst & Inst,unsigned N) const11410b57cec5SDimitry Andric void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
11420b57cec5SDimitry Andric assert(N == 1 && "Invalid number of operands!");
11430b57cec5SDimitry Andric Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
11440b57cec5SDimitry Andric }
11450b57cec5SDimitry Andric
addFGR32AsmRegOperands(MCInst & Inst,unsigned N) const11460b57cec5SDimitry Andric void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
11470b57cec5SDimitry Andric assert(N == 1 && "Invalid number of operands!");
11480b57cec5SDimitry Andric Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
11490b57cec5SDimitry Andric // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
11500b57cec5SDimitry Andric // FIXME: This should propagate failure up to parseStatement.
11510b57cec5SDimitry Andric if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
11520b57cec5SDimitry Andric AsmParser.getParser().printError(
11530b57cec5SDimitry Andric StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
11540b57cec5SDimitry Andric "registers");
11550b57cec5SDimitry Andric }
11560b57cec5SDimitry Andric
addStrictlyFGR32AsmRegOperands(MCInst & Inst,unsigned N) const11570b57cec5SDimitry Andric void addStrictlyFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
11580b57cec5SDimitry Andric assert(N == 1 && "Invalid number of operands!");
11590b57cec5SDimitry Andric Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
11600b57cec5SDimitry Andric // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
11610b57cec5SDimitry Andric if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
11620b57cec5SDimitry Andric AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
11630b57cec5SDimitry Andric "registers");
11640b57cec5SDimitry Andric }
11650b57cec5SDimitry Andric
addFCCAsmRegOperands(MCInst & Inst,unsigned N) const11660b57cec5SDimitry Andric void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
11670b57cec5SDimitry Andric assert(N == 1 && "Invalid number of operands!");
11680b57cec5SDimitry Andric Inst.addOperand(MCOperand::createReg(getFCCReg()));
11690b57cec5SDimitry Andric }
11700b57cec5SDimitry Andric
addMSA128AsmRegOperands(MCInst & Inst,unsigned N) const11710b57cec5SDimitry Andric void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
11720b57cec5SDimitry Andric assert(N == 1 && "Invalid number of operands!");
11730b57cec5SDimitry Andric Inst.addOperand(MCOperand::createReg(getMSA128Reg()));
11740b57cec5SDimitry Andric }
11750b57cec5SDimitry Andric
addMSACtrlAsmRegOperands(MCInst & Inst,unsigned N) const11760b57cec5SDimitry Andric void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
11770b57cec5SDimitry Andric assert(N == 1 && "Invalid number of operands!");
11780b57cec5SDimitry Andric Inst.addOperand(MCOperand::createReg(getMSACtrlReg()));
11790b57cec5SDimitry Andric }
11800b57cec5SDimitry Andric
addCOP0AsmRegOperands(MCInst & Inst,unsigned N) const11810b57cec5SDimitry Andric void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
11820b57cec5SDimitry Andric assert(N == 1 && "Invalid number of operands!");
11830b57cec5SDimitry Andric Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
11840b57cec5SDimitry Andric }
11850b57cec5SDimitry Andric
addCOP2AsmRegOperands(MCInst & Inst,unsigned N) const11860b57cec5SDimitry Andric void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
11870b57cec5SDimitry Andric assert(N == 1 && "Invalid number of operands!");
11880b57cec5SDimitry Andric Inst.addOperand(MCOperand::createReg(getCOP2Reg()));
11890b57cec5SDimitry Andric }
11900b57cec5SDimitry Andric
addCOP3AsmRegOperands(MCInst & Inst,unsigned N) const11910b57cec5SDimitry Andric void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
11920b57cec5SDimitry Andric assert(N == 1 && "Invalid number of operands!");
11930b57cec5SDimitry Andric Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
11940b57cec5SDimitry Andric }
11950b57cec5SDimitry Andric
addACC64DSPAsmRegOperands(MCInst & Inst,unsigned N) const11960b57cec5SDimitry Andric void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
11970b57cec5SDimitry Andric assert(N == 1 && "Invalid number of operands!");
11980b57cec5SDimitry Andric Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
11990b57cec5SDimitry Andric }
12000b57cec5SDimitry Andric
addHI32DSPAsmRegOperands(MCInst & Inst,unsigned N) const12010b57cec5SDimitry Andric void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
12020b57cec5SDimitry Andric assert(N == 1 && "Invalid number of operands!");
12030b57cec5SDimitry Andric Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));
12040b57cec5SDimitry Andric }
12050b57cec5SDimitry Andric
addLO32DSPAsmRegOperands(MCInst & Inst,unsigned N) const12060b57cec5SDimitry Andric void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
12070b57cec5SDimitry Andric assert(N == 1 && "Invalid number of operands!");
12080b57cec5SDimitry Andric Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
12090b57cec5SDimitry Andric }
12100b57cec5SDimitry Andric
addCCRAsmRegOperands(MCInst & Inst,unsigned N) const12110b57cec5SDimitry Andric void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
12120b57cec5SDimitry Andric assert(N == 1 && "Invalid number of operands!");
12130b57cec5SDimitry Andric Inst.addOperand(MCOperand::createReg(getCCRReg()));
12140b57cec5SDimitry Andric }
12150b57cec5SDimitry Andric
addHWRegsAsmRegOperands(MCInst & Inst,unsigned N) const12160b57cec5SDimitry Andric void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
12170b57cec5SDimitry Andric assert(N == 1 && "Invalid number of operands!");
12180b57cec5SDimitry Andric Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
12190b57cec5SDimitry Andric }
12200b57cec5SDimitry Andric
12210b57cec5SDimitry Andric template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
addConstantUImmOperands(MCInst & Inst,unsigned N) const12220b57cec5SDimitry Andric void addConstantUImmOperands(MCInst &Inst, unsigned N) const {
12230b57cec5SDimitry Andric assert(N == 1 && "Invalid number of operands!");
12240b57cec5SDimitry Andric uint64_t Imm = getConstantImm() - Offset;
12250b57cec5SDimitry Andric Imm &= (1ULL << Bits) - 1;
12260b57cec5SDimitry Andric Imm += Offset;
12270b57cec5SDimitry Andric Imm += AdjustOffset;
12280b57cec5SDimitry Andric Inst.addOperand(MCOperand::createImm(Imm));
12290b57cec5SDimitry Andric }
12300b57cec5SDimitry Andric
12310b57cec5SDimitry Andric template <unsigned Bits>
addSImmOperands(MCInst & Inst,unsigned N) const12320b57cec5SDimitry Andric void addSImmOperands(MCInst &Inst, unsigned N) const {
12330b57cec5SDimitry Andric if (isImm() && !isConstantImm()) {
12340b57cec5SDimitry Andric addExpr(Inst, getImm());
12350b57cec5SDimitry Andric return;
12360b57cec5SDimitry Andric }
12370b57cec5SDimitry Andric addConstantSImmOperands<Bits, 0, 0>(Inst, N);
12380b57cec5SDimitry Andric }
12390b57cec5SDimitry Andric
12400b57cec5SDimitry Andric template <unsigned Bits>
addUImmOperands(MCInst & Inst,unsigned N) const12410b57cec5SDimitry Andric void addUImmOperands(MCInst &Inst, unsigned N) const {
12420b57cec5SDimitry Andric if (isImm() && !isConstantImm()) {
12430b57cec5SDimitry Andric addExpr(Inst, getImm());
12440b57cec5SDimitry Andric return;
12450b57cec5SDimitry Andric }
12460b57cec5SDimitry Andric addConstantUImmOperands<Bits, 0, 0>(Inst, N);
12470b57cec5SDimitry Andric }
12480b57cec5SDimitry Andric
12490b57cec5SDimitry Andric template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
addConstantSImmOperands(MCInst & Inst,unsigned N) const12500b57cec5SDimitry Andric void addConstantSImmOperands(MCInst &Inst, unsigned N) const {
12510b57cec5SDimitry Andric assert(N == 1 && "Invalid number of operands!");
12520b57cec5SDimitry Andric int64_t Imm = getConstantImm() - Offset;
12530b57cec5SDimitry Andric Imm = SignExtend64<Bits>(Imm);
12540b57cec5SDimitry Andric Imm += Offset;
12550b57cec5SDimitry Andric Imm += AdjustOffset;
12560b57cec5SDimitry Andric Inst.addOperand(MCOperand::createImm(Imm));
12570b57cec5SDimitry Andric }
12580b57cec5SDimitry Andric
addImmOperands(MCInst & Inst,unsigned N) const12590b57cec5SDimitry Andric void addImmOperands(MCInst &Inst, unsigned N) const {
12600b57cec5SDimitry Andric assert(N == 1 && "Invalid number of operands!");
12610b57cec5SDimitry Andric const MCExpr *Expr = getImm();
12620b57cec5SDimitry Andric addExpr(Inst, Expr);
12630b57cec5SDimitry Andric }
12640b57cec5SDimitry Andric
addMemOperands(MCInst & Inst,unsigned N) const12650b57cec5SDimitry Andric void addMemOperands(MCInst &Inst, unsigned N) const {
12660b57cec5SDimitry Andric assert(N == 2 && "Invalid number of operands!");
12670b57cec5SDimitry Andric
12680b57cec5SDimitry Andric Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
12690b57cec5SDimitry Andric ? getMemBase()->getGPR64Reg()
12700b57cec5SDimitry Andric : getMemBase()->getGPR32Reg()));
12710b57cec5SDimitry Andric
12720b57cec5SDimitry Andric const MCExpr *Expr = getMemOff();
12730b57cec5SDimitry Andric addExpr(Inst, Expr);
12740b57cec5SDimitry Andric }
12750b57cec5SDimitry Andric
addMicroMipsMemOperands(MCInst & Inst,unsigned N) const12760b57cec5SDimitry Andric void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
12770b57cec5SDimitry Andric assert(N == 2 && "Invalid number of operands!");
12780b57cec5SDimitry Andric
12790b57cec5SDimitry Andric Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
12800b57cec5SDimitry Andric
12810b57cec5SDimitry Andric const MCExpr *Expr = getMemOff();
12820b57cec5SDimitry Andric addExpr(Inst, Expr);
12830b57cec5SDimitry Andric }
12840b57cec5SDimitry Andric
addRegListOperands(MCInst & Inst,unsigned N) const12850b57cec5SDimitry Andric void addRegListOperands(MCInst &Inst, unsigned N) const {
12860b57cec5SDimitry Andric assert(N == 1 && "Invalid number of operands!");
12870b57cec5SDimitry Andric
12880b57cec5SDimitry Andric for (auto RegNo : getRegList())
12890b57cec5SDimitry Andric Inst.addOperand(MCOperand::createReg(RegNo));
12900b57cec5SDimitry Andric }
12910b57cec5SDimitry Andric
isReg() const12920b57cec5SDimitry Andric bool isReg() const override {
12930b57cec5SDimitry Andric // As a special case until we sort out the definition of div/divu, accept
12940b57cec5SDimitry Andric // $0/$zero here so that MCK_ZERO works correctly.
12950b57cec5SDimitry Andric return isGPRAsmReg() && RegIdx.Index == 0;
12960b57cec5SDimitry Andric }
12970b57cec5SDimitry Andric
isRegIdx() const12980b57cec5SDimitry Andric bool isRegIdx() const { return Kind == k_RegisterIndex; }
isImm() const12990b57cec5SDimitry Andric bool isImm() const override { return Kind == k_Immediate; }
13000b57cec5SDimitry Andric
isConstantImm() const13010b57cec5SDimitry Andric bool isConstantImm() const {
13020b57cec5SDimitry Andric int64_t Res;
13030b57cec5SDimitry Andric return isImm() && getImm()->evaluateAsAbsolute(Res);
13040b57cec5SDimitry Andric }
13050b57cec5SDimitry Andric
isConstantImmz() const13060b57cec5SDimitry Andric bool isConstantImmz() const {
13070b57cec5SDimitry Andric return isConstantImm() && getConstantImm() == 0;
13080b57cec5SDimitry Andric }
13090b57cec5SDimitry Andric
isConstantUImm() const13100b57cec5SDimitry Andric template <unsigned Bits, int Offset = 0> bool isConstantUImm() const {
13110b57cec5SDimitry Andric return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset);
13120b57cec5SDimitry Andric }
13130b57cec5SDimitry Andric
isSImm() const13140b57cec5SDimitry Andric template <unsigned Bits> bool isSImm() const {
13150b57cec5SDimitry Andric return isConstantImm() ? isInt<Bits>(getConstantImm()) : isImm();
13160b57cec5SDimitry Andric }
13170b57cec5SDimitry Andric
isUImm() const13180b57cec5SDimitry Andric template <unsigned Bits> bool isUImm() const {
13190b57cec5SDimitry Andric return isConstantImm() ? isUInt<Bits>(getConstantImm()) : isImm();
13200b57cec5SDimitry Andric }
13210b57cec5SDimitry Andric
isAnyImm() const13220b57cec5SDimitry Andric template <unsigned Bits> bool isAnyImm() const {
13230b57cec5SDimitry Andric return isConstantImm() ? (isInt<Bits>(getConstantImm()) ||
13240b57cec5SDimitry Andric isUInt<Bits>(getConstantImm()))
13250b57cec5SDimitry Andric : isImm();
13260b57cec5SDimitry Andric }
13270b57cec5SDimitry Andric
isConstantSImm() const13280b57cec5SDimitry Andric template <unsigned Bits, int Offset = 0> bool isConstantSImm() const {
13290b57cec5SDimitry Andric return isConstantImm() && isInt<Bits>(getConstantImm() - Offset);
13300b57cec5SDimitry Andric }
13310b57cec5SDimitry Andric
isConstantUImmRange() const13320b57cec5SDimitry Andric template <unsigned Bottom, unsigned Top> bool isConstantUImmRange() const {
13330b57cec5SDimitry Andric return isConstantImm() && getConstantImm() >= Bottom &&
13340b57cec5SDimitry Andric getConstantImm() <= Top;
13350b57cec5SDimitry Andric }
13360b57cec5SDimitry Andric
isToken() const13370b57cec5SDimitry Andric bool isToken() const override {
13380b57cec5SDimitry Andric // Note: It's not possible to pretend that other operand kinds are tokens.
13390b57cec5SDimitry Andric // The matcher emitter checks tokens first.
13400b57cec5SDimitry Andric return Kind == k_Token;
13410b57cec5SDimitry Andric }
13420b57cec5SDimitry Andric
isMem() const13430b57cec5SDimitry Andric bool isMem() const override { return Kind == k_Memory; }
13440b57cec5SDimitry Andric
isConstantMemOff() const13450b57cec5SDimitry Andric bool isConstantMemOff() const {
13460b57cec5SDimitry Andric return isMem() && isa<MCConstantExpr>(getMemOff());
13470b57cec5SDimitry Andric }
13480b57cec5SDimitry Andric
13490b57cec5SDimitry Andric // Allow relocation operators.
13500b57cec5SDimitry Andric template <unsigned Bits, unsigned ShiftAmount = 0>
isMemWithSimmOffset() const13510b57cec5SDimitry Andric bool isMemWithSimmOffset() const {
13520b57cec5SDimitry Andric if (!isMem())
13530b57cec5SDimitry Andric return false;
13540b57cec5SDimitry Andric if (!getMemBase()->isGPRAsmReg())
13550b57cec5SDimitry Andric return false;
13560b57cec5SDimitry Andric if (isa<MCTargetExpr>(getMemOff()) ||
13570b57cec5SDimitry Andric (isConstantMemOff() &&
13580b57cec5SDimitry Andric isShiftedInt<Bits, ShiftAmount>(getConstantMemOff())))
13590b57cec5SDimitry Andric return true;
13600b57cec5SDimitry Andric MCValue Res;
13610b57cec5SDimitry Andric bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr, nullptr);
13620b57cec5SDimitry Andric return IsReloc && isShiftedInt<Bits, ShiftAmount>(Res.getConstant());
13630b57cec5SDimitry Andric }
13640b57cec5SDimitry Andric
isMemWithPtrSizeOffset() const13650b57cec5SDimitry Andric bool isMemWithPtrSizeOffset() const {
13660b57cec5SDimitry Andric if (!isMem())
13670b57cec5SDimitry Andric return false;
13680b57cec5SDimitry Andric if (!getMemBase()->isGPRAsmReg())
13690b57cec5SDimitry Andric return false;
13700b57cec5SDimitry Andric const unsigned PtrBits = AsmParser.getABI().ArePtrs64bit() ? 64 : 32;
13710b57cec5SDimitry Andric if (isa<MCTargetExpr>(getMemOff()) ||
13720b57cec5SDimitry Andric (isConstantMemOff() && isIntN(PtrBits, getConstantMemOff())))
13730b57cec5SDimitry Andric return true;
13740b57cec5SDimitry Andric MCValue Res;
13750b57cec5SDimitry Andric bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr, nullptr);
13760b57cec5SDimitry Andric return IsReloc && isIntN(PtrBits, Res.getConstant());
13770b57cec5SDimitry Andric }
13780b57cec5SDimitry Andric
isMemWithGRPMM16Base() const13790b57cec5SDimitry Andric bool isMemWithGRPMM16Base() const {
13800b57cec5SDimitry Andric return isMem() && getMemBase()->isMM16AsmReg();
13810b57cec5SDimitry Andric }
13820b57cec5SDimitry Andric
isMemWithUimmOffsetSP() const13830b57cec5SDimitry Andric template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
13840b57cec5SDimitry Andric return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
13850b57cec5SDimitry Andric && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
13860b57cec5SDimitry Andric }
13870b57cec5SDimitry Andric
isMemWithUimmWordAlignedOffsetSP() const13880b57cec5SDimitry Andric template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
13890b57cec5SDimitry Andric return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
13900b57cec5SDimitry Andric && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
13910b57cec5SDimitry Andric && (getMemBase()->getGPR32Reg() == Mips::SP);
13920b57cec5SDimitry Andric }
13930b57cec5SDimitry Andric
isMemWithSimmWordAlignedOffsetGP() const13940b57cec5SDimitry Andric template <unsigned Bits> bool isMemWithSimmWordAlignedOffsetGP() const {
13950b57cec5SDimitry Andric return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
13960b57cec5SDimitry Andric && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
13970b57cec5SDimitry Andric && (getMemBase()->getGPR32Reg() == Mips::GP);
13980b57cec5SDimitry Andric }
13990b57cec5SDimitry Andric
14000b57cec5SDimitry Andric template <unsigned Bits, unsigned ShiftLeftAmount>
isScaledUImm() const14010b57cec5SDimitry Andric bool isScaledUImm() const {
14020b57cec5SDimitry Andric return isConstantImm() &&
14030b57cec5SDimitry Andric isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm());
14040b57cec5SDimitry Andric }
14050b57cec5SDimitry Andric
14060b57cec5SDimitry Andric template <unsigned Bits, unsigned ShiftLeftAmount>
isScaledSImm() const14070b57cec5SDimitry Andric bool isScaledSImm() const {
14080b57cec5SDimitry Andric if (isConstantImm() &&
14090b57cec5SDimitry Andric isShiftedInt<Bits, ShiftLeftAmount>(getConstantImm()))
14100b57cec5SDimitry Andric return true;
14110b57cec5SDimitry Andric // Operand can also be a symbol or symbol plus
14120b57cec5SDimitry Andric // offset in case of relocations.
14130b57cec5SDimitry Andric if (Kind != k_Immediate)
14140b57cec5SDimitry Andric return false;
14150b57cec5SDimitry Andric MCValue Res;
14160b57cec5SDimitry Andric bool Success = getImm()->evaluateAsRelocatable(Res, nullptr, nullptr);
14170b57cec5SDimitry Andric return Success && isShiftedInt<Bits, ShiftLeftAmount>(Res.getConstant());
14180b57cec5SDimitry Andric }
14190b57cec5SDimitry Andric
isRegList16() const14200b57cec5SDimitry Andric bool isRegList16() const {
14210b57cec5SDimitry Andric if (!isRegList())
14220b57cec5SDimitry Andric return false;
14230b57cec5SDimitry Andric
14240b57cec5SDimitry Andric int Size = RegList.List->size();
14250b57cec5SDimitry Andric if (Size < 2 || Size > 5)
14260b57cec5SDimitry Andric return false;
14270b57cec5SDimitry Andric
14280b57cec5SDimitry Andric unsigned R0 = RegList.List->front();
14290b57cec5SDimitry Andric unsigned R1 = RegList.List->back();
14300b57cec5SDimitry Andric if (!((R0 == Mips::S0 && R1 == Mips::RA) ||
14310b57cec5SDimitry Andric (R0 == Mips::S0_64 && R1 == Mips::RA_64)))
14320b57cec5SDimitry Andric return false;
14330b57cec5SDimitry Andric
14340b57cec5SDimitry Andric int PrevReg = *RegList.List->begin();
14350b57cec5SDimitry Andric for (int i = 1; i < Size - 1; i++) {
14360b57cec5SDimitry Andric int Reg = (*(RegList.List))[i];
14370b57cec5SDimitry Andric if ( Reg != PrevReg + 1)
14380b57cec5SDimitry Andric return false;
14390b57cec5SDimitry Andric PrevReg = Reg;
14400b57cec5SDimitry Andric }
14410b57cec5SDimitry Andric
14420b57cec5SDimitry Andric return true;
14430b57cec5SDimitry Andric }
14440b57cec5SDimitry Andric
isInvNum() const14450b57cec5SDimitry Andric bool isInvNum() const { return Kind == k_Immediate; }
14460b57cec5SDimitry Andric
isLSAImm() const14470b57cec5SDimitry Andric bool isLSAImm() const {
14480b57cec5SDimitry Andric if (!isConstantImm())
14490b57cec5SDimitry Andric return false;
14500b57cec5SDimitry Andric int64_t Val = getConstantImm();
14510b57cec5SDimitry Andric return 1 <= Val && Val <= 4;
14520b57cec5SDimitry Andric }
14530b57cec5SDimitry Andric
isRegList() const14540b57cec5SDimitry Andric bool isRegList() const { return Kind == k_RegList; }
14550b57cec5SDimitry Andric
getToken() const14560b57cec5SDimitry Andric StringRef getToken() const {
14570b57cec5SDimitry Andric assert(Kind == k_Token && "Invalid access!");
14580b57cec5SDimitry Andric return StringRef(Tok.Data, Tok.Length);
14590b57cec5SDimitry Andric }
14600b57cec5SDimitry Andric
getReg() const1461*0fca6ea1SDimitry Andric MCRegister getReg() const override {
14620b57cec5SDimitry Andric // As a special case until we sort out the definition of div/divu, accept
14630b57cec5SDimitry Andric // $0/$zero here so that MCK_ZERO works correctly.
14640b57cec5SDimitry Andric if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
14650b57cec5SDimitry Andric RegIdx.Kind & RegKind_GPR)
14660b57cec5SDimitry Andric return getGPR32Reg(); // FIXME: GPR64 too
14670b57cec5SDimitry Andric
14680b57cec5SDimitry Andric llvm_unreachable("Invalid access!");
14690b57cec5SDimitry Andric return 0;
14700b57cec5SDimitry Andric }
14710b57cec5SDimitry Andric
getImm() const14720b57cec5SDimitry Andric const MCExpr *getImm() const {
14730b57cec5SDimitry Andric assert((Kind == k_Immediate) && "Invalid access!");
14740b57cec5SDimitry Andric return Imm.Val;
14750b57cec5SDimitry Andric }
14760b57cec5SDimitry Andric
getConstantImm() const14770b57cec5SDimitry Andric int64_t getConstantImm() const {
14780b57cec5SDimitry Andric const MCExpr *Val = getImm();
14790b57cec5SDimitry Andric int64_t Value = 0;
14800b57cec5SDimitry Andric (void)Val->evaluateAsAbsolute(Value);
14810b57cec5SDimitry Andric return Value;
14820b57cec5SDimitry Andric }
14830b57cec5SDimitry Andric
getMemBase() const14840b57cec5SDimitry Andric MipsOperand *getMemBase() const {
14850b57cec5SDimitry Andric assert((Kind == k_Memory) && "Invalid access!");
14860b57cec5SDimitry Andric return Mem.Base;
14870b57cec5SDimitry Andric }
14880b57cec5SDimitry Andric
getMemOff() const14890b57cec5SDimitry Andric const MCExpr *getMemOff() const {
14900b57cec5SDimitry Andric assert((Kind == k_Memory) && "Invalid access!");
14910b57cec5SDimitry Andric return Mem.Off;
14920b57cec5SDimitry Andric }
14930b57cec5SDimitry Andric
getConstantMemOff() const14940b57cec5SDimitry Andric int64_t getConstantMemOff() const {
14950b57cec5SDimitry Andric return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
14960b57cec5SDimitry Andric }
14970b57cec5SDimitry Andric
getRegList() const14980b57cec5SDimitry Andric const SmallVectorImpl<unsigned> &getRegList() const {
14990b57cec5SDimitry Andric assert((Kind == k_RegList) && "Invalid access!");
15000b57cec5SDimitry Andric return *(RegList.List);
15010b57cec5SDimitry Andric }
15020b57cec5SDimitry Andric
CreateToken(StringRef Str,SMLoc S,MipsAsmParser & Parser)15030b57cec5SDimitry Andric static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
15040b57cec5SDimitry Andric MipsAsmParser &Parser) {
15058bcb0991SDimitry Andric auto Op = std::make_unique<MipsOperand>(k_Token, Parser);
15060b57cec5SDimitry Andric Op->Tok.Data = Str.data();
15070b57cec5SDimitry Andric Op->Tok.Length = Str.size();
15080b57cec5SDimitry Andric Op->StartLoc = S;
15090b57cec5SDimitry Andric Op->EndLoc = S;
15100b57cec5SDimitry Andric return Op;
15110b57cec5SDimitry Andric }
15120b57cec5SDimitry Andric
15130b57cec5SDimitry Andric /// Create a numeric register (e.g. $1). The exact register remains
15140b57cec5SDimitry Andric /// unresolved until an instruction successfully matches
15150b57cec5SDimitry Andric static std::unique_ptr<MipsOperand>
createNumericReg(unsigned Index,StringRef Str,const MCRegisterInfo * RegInfo,SMLoc S,SMLoc E,MipsAsmParser & Parser)15160b57cec5SDimitry Andric createNumericReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
15170b57cec5SDimitry Andric SMLoc S, SMLoc E, MipsAsmParser &Parser) {
15180b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
15190b57cec5SDimitry Andric return CreateReg(Index, Str, RegKind_Numeric, RegInfo, S, E, Parser);
15200b57cec5SDimitry Andric }
15210b57cec5SDimitry Andric
15220b57cec5SDimitry Andric /// Create a register that is definitely a GPR.
15230b57cec5SDimitry Andric /// This is typically only used for named registers such as $gp.
15240b57cec5SDimitry Andric static std::unique_ptr<MipsOperand>
createGPRReg(unsigned Index,StringRef Str,const MCRegisterInfo * RegInfo,SMLoc S,SMLoc E,MipsAsmParser & Parser)15250b57cec5SDimitry Andric createGPRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
15260b57cec5SDimitry Andric SMLoc S, SMLoc E, MipsAsmParser &Parser) {
15270b57cec5SDimitry Andric return CreateReg(Index, Str, RegKind_GPR, RegInfo, S, E, Parser);
15280b57cec5SDimitry Andric }
15290b57cec5SDimitry Andric
15300b57cec5SDimitry Andric /// Create a register that is definitely a FGR.
15310b57cec5SDimitry Andric /// This is typically only used for named registers such as $f0.
15320b57cec5SDimitry Andric static std::unique_ptr<MipsOperand>
createFGRReg(unsigned Index,StringRef Str,const MCRegisterInfo * RegInfo,SMLoc S,SMLoc E,MipsAsmParser & Parser)15330b57cec5SDimitry Andric createFGRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
15340b57cec5SDimitry Andric SMLoc S, SMLoc E, MipsAsmParser &Parser) {
15350b57cec5SDimitry Andric return CreateReg(Index, Str, RegKind_FGR, RegInfo, S, E, Parser);
15360b57cec5SDimitry Andric }
15370b57cec5SDimitry Andric
15380b57cec5SDimitry Andric /// Create a register that is definitely a HWReg.
15390b57cec5SDimitry Andric /// This is typically only used for named registers such as $hwr_cpunum.
15400b57cec5SDimitry Andric static std::unique_ptr<MipsOperand>
createHWRegsReg(unsigned Index,StringRef Str,const MCRegisterInfo * RegInfo,SMLoc S,SMLoc E,MipsAsmParser & Parser)15410b57cec5SDimitry Andric createHWRegsReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
15420b57cec5SDimitry Andric SMLoc S, SMLoc E, MipsAsmParser &Parser) {
15430b57cec5SDimitry Andric return CreateReg(Index, Str, RegKind_HWRegs, RegInfo, S, E, Parser);
15440b57cec5SDimitry Andric }
15450b57cec5SDimitry Andric
15460b57cec5SDimitry Andric /// Create a register that is definitely an FCC.
15470b57cec5SDimitry Andric /// This is typically only used for named registers such as $fcc0.
15480b57cec5SDimitry Andric static std::unique_ptr<MipsOperand>
createFCCReg(unsigned Index,StringRef Str,const MCRegisterInfo * RegInfo,SMLoc S,SMLoc E,MipsAsmParser & Parser)15490b57cec5SDimitry Andric createFCCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
15500b57cec5SDimitry Andric SMLoc S, SMLoc E, MipsAsmParser &Parser) {
15510b57cec5SDimitry Andric return CreateReg(Index, Str, RegKind_FCC, RegInfo, S, E, Parser);
15520b57cec5SDimitry Andric }
15530b57cec5SDimitry Andric
15540b57cec5SDimitry Andric /// Create a register that is definitely an ACC.
15550b57cec5SDimitry Andric /// This is typically only used for named registers such as $ac0.
15560b57cec5SDimitry Andric static std::unique_ptr<MipsOperand>
createACCReg(unsigned Index,StringRef Str,const MCRegisterInfo * RegInfo,SMLoc S,SMLoc E,MipsAsmParser & Parser)15570b57cec5SDimitry Andric createACCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
15580b57cec5SDimitry Andric SMLoc S, SMLoc E, MipsAsmParser &Parser) {
15590b57cec5SDimitry Andric return CreateReg(Index, Str, RegKind_ACC, RegInfo, S, E, Parser);
15600b57cec5SDimitry Andric }
15610b57cec5SDimitry Andric
15620b57cec5SDimitry Andric /// Create a register that is definitely an MSA128.
15630b57cec5SDimitry Andric /// This is typically only used for named registers such as $w0.
15640b57cec5SDimitry Andric static std::unique_ptr<MipsOperand>
createMSA128Reg(unsigned Index,StringRef Str,const MCRegisterInfo * RegInfo,SMLoc S,SMLoc E,MipsAsmParser & Parser)15650b57cec5SDimitry Andric createMSA128Reg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
15660b57cec5SDimitry Andric SMLoc S, SMLoc E, MipsAsmParser &Parser) {
15670b57cec5SDimitry Andric return CreateReg(Index, Str, RegKind_MSA128, RegInfo, S, E, Parser);
15680b57cec5SDimitry Andric }
15690b57cec5SDimitry Andric
15700b57cec5SDimitry Andric /// Create a register that is definitely an MSACtrl.
15710b57cec5SDimitry Andric /// This is typically only used for named registers such as $msaaccess.
15720b57cec5SDimitry Andric static std::unique_ptr<MipsOperand>
createMSACtrlReg(unsigned Index,StringRef Str,const MCRegisterInfo * RegInfo,SMLoc S,SMLoc E,MipsAsmParser & Parser)15730b57cec5SDimitry Andric createMSACtrlReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
15740b57cec5SDimitry Andric SMLoc S, SMLoc E, MipsAsmParser &Parser) {
15750b57cec5SDimitry Andric return CreateReg(Index, Str, RegKind_MSACtrl, RegInfo, S, E, Parser);
15760b57cec5SDimitry Andric }
15770b57cec5SDimitry Andric
15780b57cec5SDimitry Andric static std::unique_ptr<MipsOperand>
CreateImm(const MCExpr * Val,SMLoc S,SMLoc E,MipsAsmParser & Parser)15790b57cec5SDimitry Andric CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
15808bcb0991SDimitry Andric auto Op = std::make_unique<MipsOperand>(k_Immediate, Parser);
15810b57cec5SDimitry Andric Op->Imm.Val = Val;
15820b57cec5SDimitry Andric Op->StartLoc = S;
15830b57cec5SDimitry Andric Op->EndLoc = E;
15840b57cec5SDimitry Andric return Op;
15850b57cec5SDimitry Andric }
15860b57cec5SDimitry Andric
15870b57cec5SDimitry Andric static std::unique_ptr<MipsOperand>
CreateMem(std::unique_ptr<MipsOperand> Base,const MCExpr * Off,SMLoc S,SMLoc E,MipsAsmParser & Parser)15880b57cec5SDimitry Andric CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
15890b57cec5SDimitry Andric SMLoc E, MipsAsmParser &Parser) {
15908bcb0991SDimitry Andric auto Op = std::make_unique<MipsOperand>(k_Memory, Parser);
15910b57cec5SDimitry Andric Op->Mem.Base = Base.release();
15920b57cec5SDimitry Andric Op->Mem.Off = Off;
15930b57cec5SDimitry Andric Op->StartLoc = S;
15940b57cec5SDimitry Andric Op->EndLoc = E;
15950b57cec5SDimitry Andric return Op;
15960b57cec5SDimitry Andric }
15970b57cec5SDimitry Andric
15980b57cec5SDimitry Andric static std::unique_ptr<MipsOperand>
CreateRegList(SmallVectorImpl<unsigned> & Regs,SMLoc StartLoc,SMLoc EndLoc,MipsAsmParser & Parser)15990b57cec5SDimitry Andric CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
16000b57cec5SDimitry Andric MipsAsmParser &Parser) {
16010b57cec5SDimitry Andric assert(Regs.size() > 0 && "Empty list not allowed");
16020b57cec5SDimitry Andric
16038bcb0991SDimitry Andric auto Op = std::make_unique<MipsOperand>(k_RegList, Parser);
16040b57cec5SDimitry Andric Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
16050b57cec5SDimitry Andric Op->StartLoc = StartLoc;
16060b57cec5SDimitry Andric Op->EndLoc = EndLoc;
16070b57cec5SDimitry Andric return Op;
16080b57cec5SDimitry Andric }
16090b57cec5SDimitry Andric
isGPRZeroAsmReg() const16100b57cec5SDimitry Andric bool isGPRZeroAsmReg() const {
16110b57cec5SDimitry Andric return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index == 0;
16120b57cec5SDimitry Andric }
16130b57cec5SDimitry Andric
isGPRNonZeroAsmReg() const16140b57cec5SDimitry Andric bool isGPRNonZeroAsmReg() const {
16150b57cec5SDimitry Andric return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index > 0 &&
16160b57cec5SDimitry Andric RegIdx.Index <= 31;
16170b57cec5SDimitry Andric }
16180b57cec5SDimitry Andric
isGPRAsmReg() const16190b57cec5SDimitry Andric bool isGPRAsmReg() const {
16200b57cec5SDimitry Andric return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
16210b57cec5SDimitry Andric }
16220b57cec5SDimitry Andric
isMM16AsmReg() const16230b57cec5SDimitry Andric bool isMM16AsmReg() const {
16240b57cec5SDimitry Andric if (!(isRegIdx() && RegIdx.Kind))
16250b57cec5SDimitry Andric return false;
16260b57cec5SDimitry Andric return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
16270b57cec5SDimitry Andric || RegIdx.Index == 16 || RegIdx.Index == 17);
16280b57cec5SDimitry Andric
16290b57cec5SDimitry Andric }
isMM16AsmRegZero() const16300b57cec5SDimitry Andric bool isMM16AsmRegZero() const {
16310b57cec5SDimitry Andric if (!(isRegIdx() && RegIdx.Kind))
16320b57cec5SDimitry Andric return false;
16330b57cec5SDimitry Andric return (RegIdx.Index == 0 ||
16340b57cec5SDimitry Andric (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
16350b57cec5SDimitry Andric RegIdx.Index == 17);
16360b57cec5SDimitry Andric }
16370b57cec5SDimitry Andric
isMM16AsmRegMoveP() const16380b57cec5SDimitry Andric bool isMM16AsmRegMoveP() const {
16390b57cec5SDimitry Andric if (!(isRegIdx() && RegIdx.Kind))
16400b57cec5SDimitry Andric return false;
16410b57cec5SDimitry Andric return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
16420b57cec5SDimitry Andric (RegIdx.Index >= 16 && RegIdx.Index <= 20));
16430b57cec5SDimitry Andric }
16440b57cec5SDimitry Andric
isMM16AsmRegMovePPairFirst() const16450b57cec5SDimitry Andric bool isMM16AsmRegMovePPairFirst() const {
16460b57cec5SDimitry Andric if (!(isRegIdx() && RegIdx.Kind))
16470b57cec5SDimitry Andric return false;
16480b57cec5SDimitry Andric return RegIdx.Index >= 4 && RegIdx.Index <= 6;
16490b57cec5SDimitry Andric }
16500b57cec5SDimitry Andric
isMM16AsmRegMovePPairSecond() const16510b57cec5SDimitry Andric bool isMM16AsmRegMovePPairSecond() const {
16520b57cec5SDimitry Andric if (!(isRegIdx() && RegIdx.Kind))
16530b57cec5SDimitry Andric return false;
16540b57cec5SDimitry Andric return (RegIdx.Index == 21 || RegIdx.Index == 22 ||
16550b57cec5SDimitry Andric (RegIdx.Index >= 5 && RegIdx.Index <= 7));
16560b57cec5SDimitry Andric }
16570b57cec5SDimitry Andric
isFGRAsmReg() const16580b57cec5SDimitry Andric bool isFGRAsmReg() const {
16590b57cec5SDimitry Andric // AFGR64 is $0-$15 but we handle this in getAFGR64()
16600b57cec5SDimitry Andric return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
16610b57cec5SDimitry Andric }
16620b57cec5SDimitry Andric
isStrictlyFGRAsmReg() const16630b57cec5SDimitry Andric bool isStrictlyFGRAsmReg() const {
16640b57cec5SDimitry Andric // AFGR64 is $0-$15 but we handle this in getAFGR64()
16650b57cec5SDimitry Andric return isRegIdx() && RegIdx.Kind == RegKind_FGR && RegIdx.Index <= 31;
16660b57cec5SDimitry Andric }
16670b57cec5SDimitry Andric
isHWRegsAsmReg() const16680b57cec5SDimitry Andric bool isHWRegsAsmReg() const {
16690b57cec5SDimitry Andric return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
16700b57cec5SDimitry Andric }
16710b57cec5SDimitry Andric
isCCRAsmReg() const16720b57cec5SDimitry Andric bool isCCRAsmReg() const {
16730b57cec5SDimitry Andric return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
16740b57cec5SDimitry Andric }
16750b57cec5SDimitry Andric
isFCCAsmReg() const16760b57cec5SDimitry Andric bool isFCCAsmReg() const {
16770b57cec5SDimitry Andric if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
16780b57cec5SDimitry Andric return false;
16790b57cec5SDimitry Andric return RegIdx.Index <= 7;
16800b57cec5SDimitry Andric }
16810b57cec5SDimitry Andric
isACCAsmReg() const16820b57cec5SDimitry Andric bool isACCAsmReg() const {
16830b57cec5SDimitry Andric return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
16840b57cec5SDimitry Andric }
16850b57cec5SDimitry Andric
isCOP0AsmReg() const16860b57cec5SDimitry Andric bool isCOP0AsmReg() const {
16870b57cec5SDimitry Andric return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
16880b57cec5SDimitry Andric }
16890b57cec5SDimitry Andric
isCOP2AsmReg() const16900b57cec5SDimitry Andric bool isCOP2AsmReg() const {
16910b57cec5SDimitry Andric return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
16920b57cec5SDimitry Andric }
16930b57cec5SDimitry Andric
isCOP3AsmReg() const16940b57cec5SDimitry Andric bool isCOP3AsmReg() const {
16950b57cec5SDimitry Andric return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
16960b57cec5SDimitry Andric }
16970b57cec5SDimitry Andric
isMSA128AsmReg() const16980b57cec5SDimitry Andric bool isMSA128AsmReg() const {
16990b57cec5SDimitry Andric return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
17000b57cec5SDimitry Andric }
17010b57cec5SDimitry Andric
isMSACtrlAsmReg() const17020b57cec5SDimitry Andric bool isMSACtrlAsmReg() const {
17030b57cec5SDimitry Andric return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
17040b57cec5SDimitry Andric }
17050b57cec5SDimitry Andric
17060b57cec5SDimitry Andric /// getStartLoc - Get the location of the first token of this operand.
getStartLoc() const17070b57cec5SDimitry Andric SMLoc getStartLoc() const override { return StartLoc; }
17080b57cec5SDimitry Andric /// getEndLoc - Get the location of the last token of this operand.
getEndLoc() const17090b57cec5SDimitry Andric SMLoc getEndLoc() const override { return EndLoc; }
17100b57cec5SDimitry Andric
print(raw_ostream & OS) const17110b57cec5SDimitry Andric void print(raw_ostream &OS) const override {
17120b57cec5SDimitry Andric switch (Kind) {
17130b57cec5SDimitry Andric case k_Immediate:
17140b57cec5SDimitry Andric OS << "Imm<";
17150b57cec5SDimitry Andric OS << *Imm.Val;
17160b57cec5SDimitry Andric OS << ">";
17170b57cec5SDimitry Andric break;
17180b57cec5SDimitry Andric case k_Memory:
17190b57cec5SDimitry Andric OS << "Mem<";
17200b57cec5SDimitry Andric Mem.Base->print(OS);
17210b57cec5SDimitry Andric OS << ", ";
17220b57cec5SDimitry Andric OS << *Mem.Off;
17230b57cec5SDimitry Andric OS << ">";
17240b57cec5SDimitry Andric break;
17250b57cec5SDimitry Andric case k_RegisterIndex:
17260b57cec5SDimitry Andric OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ", "
17270b57cec5SDimitry Andric << StringRef(RegIdx.Tok.Data, RegIdx.Tok.Length) << ">";
17280b57cec5SDimitry Andric break;
17290b57cec5SDimitry Andric case k_Token:
17300b57cec5SDimitry Andric OS << getToken();
17310b57cec5SDimitry Andric break;
17320b57cec5SDimitry Andric case k_RegList:
17330b57cec5SDimitry Andric OS << "RegList< ";
17340b57cec5SDimitry Andric for (auto Reg : (*RegList.List))
17350b57cec5SDimitry Andric OS << Reg << " ";
17360b57cec5SDimitry Andric OS << ">";
17370b57cec5SDimitry Andric break;
17380b57cec5SDimitry Andric }
17390b57cec5SDimitry Andric }
17400b57cec5SDimitry Andric
isValidForTie(const MipsOperand & Other) const17410b57cec5SDimitry Andric bool isValidForTie(const MipsOperand &Other) const {
17420b57cec5SDimitry Andric if (Kind != Other.Kind)
17430b57cec5SDimitry Andric return false;
17440b57cec5SDimitry Andric
17450b57cec5SDimitry Andric switch (Kind) {
17460b57cec5SDimitry Andric default:
17470b57cec5SDimitry Andric llvm_unreachable("Unexpected kind");
17480b57cec5SDimitry Andric return false;
17490b57cec5SDimitry Andric case k_RegisterIndex: {
17500b57cec5SDimitry Andric StringRef Token(RegIdx.Tok.Data, RegIdx.Tok.Length);
17510b57cec5SDimitry Andric StringRef OtherToken(Other.RegIdx.Tok.Data, Other.RegIdx.Tok.Length);
17520b57cec5SDimitry Andric return Token == OtherToken;
17530b57cec5SDimitry Andric }
17540b57cec5SDimitry Andric }
17550b57cec5SDimitry Andric }
17560b57cec5SDimitry Andric }; // class MipsOperand
17570b57cec5SDimitry Andric
17580b57cec5SDimitry Andric } // end anonymous namespace
17590b57cec5SDimitry Andric
hasShortDelaySlot(MCInst & Inst)17600b57cec5SDimitry Andric static bool hasShortDelaySlot(MCInst &Inst) {
17610b57cec5SDimitry Andric switch (Inst.getOpcode()) {
17620b57cec5SDimitry Andric case Mips::BEQ_MM:
17630b57cec5SDimitry Andric case Mips::BNE_MM:
17640b57cec5SDimitry Andric case Mips::BLTZ_MM:
17650b57cec5SDimitry Andric case Mips::BGEZ_MM:
17660b57cec5SDimitry Andric case Mips::BLEZ_MM:
17670b57cec5SDimitry Andric case Mips::BGTZ_MM:
17680b57cec5SDimitry Andric case Mips::JRC16_MM:
17690b57cec5SDimitry Andric case Mips::JALS_MM:
17700b57cec5SDimitry Andric case Mips::JALRS_MM:
17710b57cec5SDimitry Andric case Mips::JALRS16_MM:
17720b57cec5SDimitry Andric case Mips::BGEZALS_MM:
17730b57cec5SDimitry Andric case Mips::BLTZALS_MM:
17740b57cec5SDimitry Andric return true;
17750b57cec5SDimitry Andric case Mips::J_MM:
17760b57cec5SDimitry Andric return !Inst.getOperand(0).isReg();
17770b57cec5SDimitry Andric default:
17780b57cec5SDimitry Andric return false;
17790b57cec5SDimitry Andric }
17800b57cec5SDimitry Andric }
17810b57cec5SDimitry Andric
getSingleMCSymbol(const MCExpr * Expr)17820b57cec5SDimitry Andric static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
17830b57cec5SDimitry Andric if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
17840b57cec5SDimitry Andric return &SRExpr->getSymbol();
17850b57cec5SDimitry Andric }
17860b57cec5SDimitry Andric
17870b57cec5SDimitry Andric if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
17880b57cec5SDimitry Andric const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
17890b57cec5SDimitry Andric const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
17900b57cec5SDimitry Andric
17910b57cec5SDimitry Andric if (LHSSym)
17920b57cec5SDimitry Andric return LHSSym;
17930b57cec5SDimitry Andric
17940b57cec5SDimitry Andric if (RHSSym)
17950b57cec5SDimitry Andric return RHSSym;
17960b57cec5SDimitry Andric
17970b57cec5SDimitry Andric return nullptr;
17980b57cec5SDimitry Andric }
17990b57cec5SDimitry Andric
18000b57cec5SDimitry Andric if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
18010b57cec5SDimitry Andric return getSingleMCSymbol(UExpr->getSubExpr());
18020b57cec5SDimitry Andric
18030b57cec5SDimitry Andric return nullptr;
18040b57cec5SDimitry Andric }
18050b57cec5SDimitry Andric
countMCSymbolRefExpr(const MCExpr * Expr)18060b57cec5SDimitry Andric static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
18070b57cec5SDimitry Andric if (isa<MCSymbolRefExpr>(Expr))
18080b57cec5SDimitry Andric return 1;
18090b57cec5SDimitry Andric
18100b57cec5SDimitry Andric if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
18110b57cec5SDimitry Andric return countMCSymbolRefExpr(BExpr->getLHS()) +
18120b57cec5SDimitry Andric countMCSymbolRefExpr(BExpr->getRHS());
18130b57cec5SDimitry Andric
18140b57cec5SDimitry Andric if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
18150b57cec5SDimitry Andric return countMCSymbolRefExpr(UExpr->getSubExpr());
18160b57cec5SDimitry Andric
18170b57cec5SDimitry Andric return 0;
18180b57cec5SDimitry Andric }
18190b57cec5SDimitry Andric
isEvaluated(const MCExpr * Expr)1820480093f4SDimitry Andric static bool isEvaluated(const MCExpr *Expr) {
1821480093f4SDimitry Andric switch (Expr->getKind()) {
1822480093f4SDimitry Andric case MCExpr::Constant:
1823480093f4SDimitry Andric return true;
1824480093f4SDimitry Andric case MCExpr::SymbolRef:
1825480093f4SDimitry Andric return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
1826480093f4SDimitry Andric case MCExpr::Binary: {
1827480093f4SDimitry Andric const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr);
1828480093f4SDimitry Andric if (!isEvaluated(BE->getLHS()))
1829480093f4SDimitry Andric return false;
1830480093f4SDimitry Andric return isEvaluated(BE->getRHS());
1831480093f4SDimitry Andric }
1832480093f4SDimitry Andric case MCExpr::Unary:
1833480093f4SDimitry Andric return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
1834480093f4SDimitry Andric case MCExpr::Target:
1835480093f4SDimitry Andric return true;
1836480093f4SDimitry Andric }
1837480093f4SDimitry Andric return false;
1838480093f4SDimitry Andric }
1839480093f4SDimitry Andric
needsExpandMemInst(MCInst & Inst,const MCInstrDesc & MCID)1840bdd1243dSDimitry Andric static bool needsExpandMemInst(MCInst &Inst, const MCInstrDesc &MCID) {
1841480093f4SDimitry Andric unsigned NumOp = MCID.getNumOperands();
1842480093f4SDimitry Andric if (NumOp != 3 && NumOp != 4)
1843480093f4SDimitry Andric return false;
1844480093f4SDimitry Andric
1845bdd1243dSDimitry Andric const MCOperandInfo &OpInfo = MCID.operands()[NumOp - 1];
1846480093f4SDimitry Andric if (OpInfo.OperandType != MCOI::OPERAND_MEMORY &&
1847480093f4SDimitry Andric OpInfo.OperandType != MCOI::OPERAND_UNKNOWN &&
1848480093f4SDimitry Andric OpInfo.OperandType != MipsII::OPERAND_MEM_SIMM9)
1849480093f4SDimitry Andric return false;
1850480093f4SDimitry Andric
1851480093f4SDimitry Andric MCOperand &Op = Inst.getOperand(NumOp - 1);
1852480093f4SDimitry Andric if (Op.isImm()) {
1853480093f4SDimitry Andric if (OpInfo.OperandType == MipsII::OPERAND_MEM_SIMM9)
1854480093f4SDimitry Andric return !isInt<9>(Op.getImm());
1855480093f4SDimitry Andric // Offset can't exceed 16bit value.
1856480093f4SDimitry Andric return !isInt<16>(Op.getImm());
1857480093f4SDimitry Andric }
1858480093f4SDimitry Andric
1859480093f4SDimitry Andric if (Op.isExpr()) {
1860480093f4SDimitry Andric const MCExpr *Expr = Op.getExpr();
1861480093f4SDimitry Andric if (Expr->getKind() != MCExpr::SymbolRef)
1862480093f4SDimitry Andric return !isEvaluated(Expr);
1863480093f4SDimitry Andric
1864480093f4SDimitry Andric // Expand symbol.
1865480093f4SDimitry Andric const MCSymbolRefExpr *SR = static_cast<const MCSymbolRefExpr *>(Expr);
1866480093f4SDimitry Andric return SR->getKind() == MCSymbolRefExpr::VK_None;
1867480093f4SDimitry Andric }
1868480093f4SDimitry Andric
1869480093f4SDimitry Andric return false;
1870480093f4SDimitry Andric }
1871480093f4SDimitry Andric
processInstruction(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)18720b57cec5SDimitry Andric bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
18730b57cec5SDimitry Andric MCStreamer &Out,
18740b57cec5SDimitry Andric const MCSubtargetInfo *STI) {
18750b57cec5SDimitry Andric MipsTargetStreamer &TOut = getTargetStreamer();
1876480093f4SDimitry Andric const unsigned Opcode = Inst.getOpcode();
1877bdd1243dSDimitry Andric const MCInstrDesc &MCID = MII.get(Opcode);
18780b57cec5SDimitry Andric bool ExpandedJalSym = false;
18790b57cec5SDimitry Andric
18800b57cec5SDimitry Andric Inst.setLoc(IDLoc);
18810b57cec5SDimitry Andric
18820b57cec5SDimitry Andric if (MCID.isBranch() || MCID.isCall()) {
18830b57cec5SDimitry Andric MCOperand Offset;
18840b57cec5SDimitry Andric
18850b57cec5SDimitry Andric switch (Opcode) {
18860b57cec5SDimitry Andric default:
18870b57cec5SDimitry Andric break;
18880b57cec5SDimitry Andric case Mips::BBIT0:
18890b57cec5SDimitry Andric case Mips::BBIT032:
18900b57cec5SDimitry Andric case Mips::BBIT1:
18910b57cec5SDimitry Andric case Mips::BBIT132:
18920b57cec5SDimitry Andric assert(hasCnMips() && "instruction only valid for octeon cpus");
1893bdd1243dSDimitry Andric [[fallthrough]];
18940b57cec5SDimitry Andric
18950b57cec5SDimitry Andric case Mips::BEQ:
18960b57cec5SDimitry Andric case Mips::BNE:
18970b57cec5SDimitry Andric case Mips::BEQ_MM:
18980b57cec5SDimitry Andric case Mips::BNE_MM:
18990b57cec5SDimitry Andric assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
19000b57cec5SDimitry Andric Offset = Inst.getOperand(2);
19010b57cec5SDimitry Andric if (!Offset.isImm())
19020b57cec5SDimitry Andric break; // We'll deal with this situation later on when applying fixups.
19030b57cec5SDimitry Andric if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
19040b57cec5SDimitry Andric return Error(IDLoc, "branch target out of range");
19058bcb0991SDimitry Andric if (offsetToAlignment(Offset.getImm(),
19068bcb0991SDimitry Andric (inMicroMipsMode() ? Align(2) : Align(4))))
19070b57cec5SDimitry Andric return Error(IDLoc, "branch to misaligned address");
19080b57cec5SDimitry Andric break;
19090b57cec5SDimitry Andric case Mips::BGEZ:
19100b57cec5SDimitry Andric case Mips::BGTZ:
19110b57cec5SDimitry Andric case Mips::BLEZ:
19120b57cec5SDimitry Andric case Mips::BLTZ:
19130b57cec5SDimitry Andric case Mips::BGEZAL:
19140b57cec5SDimitry Andric case Mips::BLTZAL:
19150b57cec5SDimitry Andric case Mips::BC1F:
19160b57cec5SDimitry Andric case Mips::BC1T:
19170b57cec5SDimitry Andric case Mips::BGEZ_MM:
19180b57cec5SDimitry Andric case Mips::BGTZ_MM:
19190b57cec5SDimitry Andric case Mips::BLEZ_MM:
19200b57cec5SDimitry Andric case Mips::BLTZ_MM:
19210b57cec5SDimitry Andric case Mips::BGEZAL_MM:
19220b57cec5SDimitry Andric case Mips::BLTZAL_MM:
19230b57cec5SDimitry Andric case Mips::BC1F_MM:
19240b57cec5SDimitry Andric case Mips::BC1T_MM:
19250b57cec5SDimitry Andric case Mips::BC1EQZC_MMR6:
19260b57cec5SDimitry Andric case Mips::BC1NEZC_MMR6:
19270b57cec5SDimitry Andric case Mips::BC2EQZC_MMR6:
19280b57cec5SDimitry Andric case Mips::BC2NEZC_MMR6:
19290b57cec5SDimitry Andric assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
19300b57cec5SDimitry Andric Offset = Inst.getOperand(1);
19310b57cec5SDimitry Andric if (!Offset.isImm())
19320b57cec5SDimitry Andric break; // We'll deal with this situation later on when applying fixups.
19330b57cec5SDimitry Andric if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
19340b57cec5SDimitry Andric return Error(IDLoc, "branch target out of range");
19358bcb0991SDimitry Andric if (offsetToAlignment(Offset.getImm(),
19368bcb0991SDimitry Andric (inMicroMipsMode() ? Align(2) : Align(4))))
19370b57cec5SDimitry Andric return Error(IDLoc, "branch to misaligned address");
19380b57cec5SDimitry Andric break;
19390b57cec5SDimitry Andric case Mips::BGEC: case Mips::BGEC_MMR6:
19400b57cec5SDimitry Andric case Mips::BLTC: case Mips::BLTC_MMR6:
19410b57cec5SDimitry Andric case Mips::BGEUC: case Mips::BGEUC_MMR6:
19420b57cec5SDimitry Andric case Mips::BLTUC: case Mips::BLTUC_MMR6:
19430b57cec5SDimitry Andric case Mips::BEQC: case Mips::BEQC_MMR6:
19440b57cec5SDimitry Andric case Mips::BNEC: case Mips::BNEC_MMR6:
19450b57cec5SDimitry Andric assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
19460b57cec5SDimitry Andric Offset = Inst.getOperand(2);
19470b57cec5SDimitry Andric if (!Offset.isImm())
19480b57cec5SDimitry Andric break; // We'll deal with this situation later on when applying fixups.
19490b57cec5SDimitry Andric if (!isIntN(18, Offset.getImm()))
19500b57cec5SDimitry Andric return Error(IDLoc, "branch target out of range");
19518bcb0991SDimitry Andric if (offsetToAlignment(Offset.getImm(), Align(4)))
19520b57cec5SDimitry Andric return Error(IDLoc, "branch to misaligned address");
19530b57cec5SDimitry Andric break;
19540b57cec5SDimitry Andric case Mips::BLEZC: case Mips::BLEZC_MMR6:
19550b57cec5SDimitry Andric case Mips::BGEZC: case Mips::BGEZC_MMR6:
19560b57cec5SDimitry Andric case Mips::BGTZC: case Mips::BGTZC_MMR6:
19570b57cec5SDimitry Andric case Mips::BLTZC: case Mips::BLTZC_MMR6:
19580b57cec5SDimitry Andric assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
19590b57cec5SDimitry Andric Offset = Inst.getOperand(1);
19600b57cec5SDimitry Andric if (!Offset.isImm())
19610b57cec5SDimitry Andric break; // We'll deal with this situation later on when applying fixups.
19620b57cec5SDimitry Andric if (!isIntN(18, Offset.getImm()))
19630b57cec5SDimitry Andric return Error(IDLoc, "branch target out of range");
19648bcb0991SDimitry Andric if (offsetToAlignment(Offset.getImm(), Align(4)))
19650b57cec5SDimitry Andric return Error(IDLoc, "branch to misaligned address");
19660b57cec5SDimitry Andric break;
19670b57cec5SDimitry Andric case Mips::BEQZC: case Mips::BEQZC_MMR6:
19680b57cec5SDimitry Andric case Mips::BNEZC: case Mips::BNEZC_MMR6:
19690b57cec5SDimitry Andric assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
19700b57cec5SDimitry Andric Offset = Inst.getOperand(1);
19710b57cec5SDimitry Andric if (!Offset.isImm())
19720b57cec5SDimitry Andric break; // We'll deal with this situation later on when applying fixups.
19730b57cec5SDimitry Andric if (!isIntN(23, Offset.getImm()))
19740b57cec5SDimitry Andric return Error(IDLoc, "branch target out of range");
19758bcb0991SDimitry Andric if (offsetToAlignment(Offset.getImm(), Align(4)))
19760b57cec5SDimitry Andric return Error(IDLoc, "branch to misaligned address");
19770b57cec5SDimitry Andric break;
19780b57cec5SDimitry Andric case Mips::BEQZ16_MM:
19790b57cec5SDimitry Andric case Mips::BEQZC16_MMR6:
19800b57cec5SDimitry Andric case Mips::BNEZ16_MM:
19810b57cec5SDimitry Andric case Mips::BNEZC16_MMR6:
19820b57cec5SDimitry Andric assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
19830b57cec5SDimitry Andric Offset = Inst.getOperand(1);
19840b57cec5SDimitry Andric if (!Offset.isImm())
19850b57cec5SDimitry Andric break; // We'll deal with this situation later on when applying fixups.
19860b57cec5SDimitry Andric if (!isInt<8>(Offset.getImm()))
19870b57cec5SDimitry Andric return Error(IDLoc, "branch target out of range");
19888bcb0991SDimitry Andric if (offsetToAlignment(Offset.getImm(), Align(2)))
19890b57cec5SDimitry Andric return Error(IDLoc, "branch to misaligned address");
19900b57cec5SDimitry Andric break;
19910b57cec5SDimitry Andric }
19920b57cec5SDimitry Andric }
19930b57cec5SDimitry Andric
19940b57cec5SDimitry Andric // SSNOP is deprecated on MIPS32r6/MIPS64r6
19950b57cec5SDimitry Andric // We still accept it but it is a normal nop.
1996480093f4SDimitry Andric if (hasMips32r6() && Opcode == Mips::SSNOP) {
19970b57cec5SDimitry Andric std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
19980b57cec5SDimitry Andric Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
19990b57cec5SDimitry Andric "nop instruction");
20000b57cec5SDimitry Andric }
20010b57cec5SDimitry Andric
20020b57cec5SDimitry Andric if (hasCnMips()) {
20030b57cec5SDimitry Andric MCOperand Opnd;
20040b57cec5SDimitry Andric int Imm;
20050b57cec5SDimitry Andric
20060b57cec5SDimitry Andric switch (Opcode) {
20070b57cec5SDimitry Andric default:
20080b57cec5SDimitry Andric break;
20090b57cec5SDimitry Andric
20100b57cec5SDimitry Andric case Mips::BBIT0:
20110b57cec5SDimitry Andric case Mips::BBIT032:
20120b57cec5SDimitry Andric case Mips::BBIT1:
20130b57cec5SDimitry Andric case Mips::BBIT132:
20140b57cec5SDimitry Andric assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
20150b57cec5SDimitry Andric // The offset is handled above
20160b57cec5SDimitry Andric Opnd = Inst.getOperand(1);
20170b57cec5SDimitry Andric if (!Opnd.isImm())
20180b57cec5SDimitry Andric return Error(IDLoc, "expected immediate operand kind");
20190b57cec5SDimitry Andric Imm = Opnd.getImm();
20200b57cec5SDimitry Andric if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
20210b57cec5SDimitry Andric Opcode == Mips::BBIT1 ? 63 : 31))
20220b57cec5SDimitry Andric return Error(IDLoc, "immediate operand value out of range");
20230b57cec5SDimitry Andric if (Imm > 31) {
20240b57cec5SDimitry Andric Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
20250b57cec5SDimitry Andric : Mips::BBIT132);
20260b57cec5SDimitry Andric Inst.getOperand(1).setImm(Imm - 32);
20270b57cec5SDimitry Andric }
20280b57cec5SDimitry Andric break;
20290b57cec5SDimitry Andric
20300b57cec5SDimitry Andric case Mips::SEQi:
20310b57cec5SDimitry Andric case Mips::SNEi:
20320b57cec5SDimitry Andric assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
20330b57cec5SDimitry Andric Opnd = Inst.getOperand(2);
20340b57cec5SDimitry Andric if (!Opnd.isImm())
20350b57cec5SDimitry Andric return Error(IDLoc, "expected immediate operand kind");
20360b57cec5SDimitry Andric Imm = Opnd.getImm();
20370b57cec5SDimitry Andric if (!isInt<10>(Imm))
20380b57cec5SDimitry Andric return Error(IDLoc, "immediate operand value out of range");
20390b57cec5SDimitry Andric break;
20400b57cec5SDimitry Andric }
20410b57cec5SDimitry Andric }
20420b57cec5SDimitry Andric
20430b57cec5SDimitry Andric // Warn on division by zero. We're checking here as all instructions get
20440b57cec5SDimitry Andric // processed here, not just the macros that need expansion.
20450b57cec5SDimitry Andric //
20460b57cec5SDimitry Andric // The MIPS backend models most of the divison instructions and macros as
20470b57cec5SDimitry Andric // three operand instructions. The pre-R6 divide instructions however have
20480b57cec5SDimitry Andric // two operands and explicitly define HI/LO as part of the instruction,
20490b57cec5SDimitry Andric // not in the operands.
20500b57cec5SDimitry Andric unsigned FirstOp = 1;
20510b57cec5SDimitry Andric unsigned SecondOp = 2;
2052480093f4SDimitry Andric switch (Opcode) {
20530b57cec5SDimitry Andric default:
20540b57cec5SDimitry Andric break;
20550b57cec5SDimitry Andric case Mips::SDivIMacro:
20560b57cec5SDimitry Andric case Mips::UDivIMacro:
20570b57cec5SDimitry Andric case Mips::DSDivIMacro:
20580b57cec5SDimitry Andric case Mips::DUDivIMacro:
20590b57cec5SDimitry Andric if (Inst.getOperand(2).getImm() == 0) {
20600b57cec5SDimitry Andric if (Inst.getOperand(1).getReg() == Mips::ZERO ||
20610b57cec5SDimitry Andric Inst.getOperand(1).getReg() == Mips::ZERO_64)
20620b57cec5SDimitry Andric Warning(IDLoc, "dividing zero by zero");
20630b57cec5SDimitry Andric else
20640b57cec5SDimitry Andric Warning(IDLoc, "division by zero");
20650b57cec5SDimitry Andric }
20660b57cec5SDimitry Andric break;
20670b57cec5SDimitry Andric case Mips::DSDIV:
20680b57cec5SDimitry Andric case Mips::SDIV:
20690b57cec5SDimitry Andric case Mips::UDIV:
20700b57cec5SDimitry Andric case Mips::DUDIV:
20710b57cec5SDimitry Andric case Mips::UDIV_MM:
20720b57cec5SDimitry Andric case Mips::SDIV_MM:
20730b57cec5SDimitry Andric FirstOp = 0;
20740b57cec5SDimitry Andric SecondOp = 1;
2075bdd1243dSDimitry Andric [[fallthrough]];
20760b57cec5SDimitry Andric case Mips::SDivMacro:
20770b57cec5SDimitry Andric case Mips::DSDivMacro:
20780b57cec5SDimitry Andric case Mips::UDivMacro:
20790b57cec5SDimitry Andric case Mips::DUDivMacro:
20800b57cec5SDimitry Andric case Mips::DIV:
20810b57cec5SDimitry Andric case Mips::DIVU:
20820b57cec5SDimitry Andric case Mips::DDIV:
20830b57cec5SDimitry Andric case Mips::DDIVU:
20840b57cec5SDimitry Andric case Mips::DIVU_MMR6:
20850b57cec5SDimitry Andric case Mips::DIV_MMR6:
20860b57cec5SDimitry Andric if (Inst.getOperand(SecondOp).getReg() == Mips::ZERO ||
20870b57cec5SDimitry Andric Inst.getOperand(SecondOp).getReg() == Mips::ZERO_64) {
20880b57cec5SDimitry Andric if (Inst.getOperand(FirstOp).getReg() == Mips::ZERO ||
20890b57cec5SDimitry Andric Inst.getOperand(FirstOp).getReg() == Mips::ZERO_64)
20900b57cec5SDimitry Andric Warning(IDLoc, "dividing zero by zero");
20910b57cec5SDimitry Andric else
20920b57cec5SDimitry Andric Warning(IDLoc, "division by zero");
20930b57cec5SDimitry Andric }
20940b57cec5SDimitry Andric break;
20950b57cec5SDimitry Andric }
20960b57cec5SDimitry Andric
20970b57cec5SDimitry Andric // For PIC code convert unconditional jump to unconditional branch.
2098480093f4SDimitry Andric if ((Opcode == Mips::J || Opcode == Mips::J_MM) && inPicMode()) {
20990b57cec5SDimitry Andric MCInst BInst;
21000b57cec5SDimitry Andric BInst.setOpcode(inMicroMipsMode() ? Mips::BEQ_MM : Mips::BEQ);
21010b57cec5SDimitry Andric BInst.addOperand(MCOperand::createReg(Mips::ZERO));
21020b57cec5SDimitry Andric BInst.addOperand(MCOperand::createReg(Mips::ZERO));
21030b57cec5SDimitry Andric BInst.addOperand(Inst.getOperand(0));
21040b57cec5SDimitry Andric Inst = BInst;
21050b57cec5SDimitry Andric }
21060b57cec5SDimitry Andric
21070b57cec5SDimitry Andric // This expansion is not in a function called by tryExpandInstruction()
21080b57cec5SDimitry Andric // because the pseudo-instruction doesn't have a distinct opcode.
2109480093f4SDimitry Andric if ((Opcode == Mips::JAL || Opcode == Mips::JAL_MM) && inPicMode()) {
21100b57cec5SDimitry Andric warnIfNoMacro(IDLoc);
21110b57cec5SDimitry Andric
21120b57cec5SDimitry Andric const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
21130b57cec5SDimitry Andric
21140b57cec5SDimitry Andric // We can do this expansion if there's only 1 symbol in the argument
21150b57cec5SDimitry Andric // expression.
21160b57cec5SDimitry Andric if (countMCSymbolRefExpr(JalExpr) > 1)
21170b57cec5SDimitry Andric return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
21180b57cec5SDimitry Andric
21190b57cec5SDimitry Andric // FIXME: This is checking the expression can be handled by the later stages
21200b57cec5SDimitry Andric // of the assembler. We ought to leave it to those later stages.
21210b57cec5SDimitry Andric const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
21220b57cec5SDimitry Andric
2123480093f4SDimitry Andric if (expandLoadAddress(Mips::T9, Mips::NoRegister, Inst.getOperand(0),
2124480093f4SDimitry Andric !isGP64bit(), IDLoc, Out, STI))
2125480093f4SDimitry Andric return true;
21260b57cec5SDimitry Andric
21270b57cec5SDimitry Andric MCInst JalrInst;
2128480093f4SDimitry Andric if (inMicroMipsMode())
2129480093f4SDimitry Andric JalrInst.setOpcode(IsCpRestoreSet ? Mips::JALRS_MM : Mips::JALR_MM);
21300b57cec5SDimitry Andric else
2131480093f4SDimitry Andric JalrInst.setOpcode(Mips::JALR);
21320b57cec5SDimitry Andric JalrInst.addOperand(MCOperand::createReg(Mips::RA));
21330b57cec5SDimitry Andric JalrInst.addOperand(MCOperand::createReg(Mips::T9));
21340b57cec5SDimitry Andric
2135480093f4SDimitry Andric if (isJalrRelocAvailable(JalExpr)) {
21360b57cec5SDimitry Andric // As an optimization hint for the linker, before the JALR we add:
21370b57cec5SDimitry Andric // .reloc tmplabel, R_{MICRO}MIPS_JALR, symbol
21380b57cec5SDimitry Andric // tmplabel:
21390b57cec5SDimitry Andric MCSymbol *TmpLabel = getContext().createTempSymbol();
21400b57cec5SDimitry Andric const MCExpr *TmpExpr = MCSymbolRefExpr::create(TmpLabel, getContext());
21410b57cec5SDimitry Andric const MCExpr *RelocJalrExpr =
21420b57cec5SDimitry Andric MCSymbolRefExpr::create(JalSym, MCSymbolRefExpr::VK_None,
21430b57cec5SDimitry Andric getContext(), IDLoc);
21440b57cec5SDimitry Andric
21455ffd83dbSDimitry Andric TOut.getStreamer().emitRelocDirective(
21465ffd83dbSDimitry Andric *TmpExpr, inMicroMipsMode() ? "R_MICROMIPS_JALR" : "R_MIPS_JALR",
21470b57cec5SDimitry Andric RelocJalrExpr, IDLoc, *STI);
21485ffd83dbSDimitry Andric TOut.getStreamer().emitLabel(TmpLabel);
21490b57cec5SDimitry Andric }
21500b57cec5SDimitry Andric
21510b57cec5SDimitry Andric Inst = JalrInst;
21520b57cec5SDimitry Andric ExpandedJalSym = true;
21530b57cec5SDimitry Andric }
21540b57cec5SDimitry Andric
2155480093f4SDimitry Andric if (MCID.mayLoad() || MCID.mayStore()) {
21560b57cec5SDimitry Andric // Check the offset of memory operand, if it is a symbol
21570b57cec5SDimitry Andric // reference or immediate we may have to expand instructions.
2158bdd1243dSDimitry Andric if (needsExpandMemInst(Inst, MCID)) {
2159bdd1243dSDimitry Andric switch (MCID.operands()[MCID.getNumOperands() - 1].OperandType) {
2160480093f4SDimitry Andric case MipsII::OPERAND_MEM_SIMM9:
2161480093f4SDimitry Andric expandMem9Inst(Inst, IDLoc, Out, STI, MCID.mayLoad());
2162480093f4SDimitry Andric break;
2163480093f4SDimitry Andric default:
2164480093f4SDimitry Andric expandMem16Inst(Inst, IDLoc, Out, STI, MCID.mayLoad());
2165480093f4SDimitry Andric break;
21660b57cec5SDimitry Andric }
21670b57cec5SDimitry Andric return getParser().hasPendingError();
21680b57cec5SDimitry Andric }
21690b57cec5SDimitry Andric }
21700b57cec5SDimitry Andric
21710b57cec5SDimitry Andric if (inMicroMipsMode()) {
2172480093f4SDimitry Andric if (MCID.mayLoad() && Opcode != Mips::LWP_MM) {
21730b57cec5SDimitry Andric // Try to create 16-bit GP relative load instruction.
21740b57cec5SDimitry Andric for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
2175bdd1243dSDimitry Andric const MCOperandInfo &OpInfo = MCID.operands()[i];
21760b57cec5SDimitry Andric if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
21770b57cec5SDimitry Andric (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
21780b57cec5SDimitry Andric MCOperand &Op = Inst.getOperand(i);
21790b57cec5SDimitry Andric if (Op.isImm()) {
21800b57cec5SDimitry Andric int MemOffset = Op.getImm();
21810b57cec5SDimitry Andric MCOperand &DstReg = Inst.getOperand(0);
21820b57cec5SDimitry Andric MCOperand &BaseReg = Inst.getOperand(1);
21830b57cec5SDimitry Andric if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&
21840b57cec5SDimitry Andric getContext().getRegisterInfo()->getRegClass(
21850b57cec5SDimitry Andric Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
21860b57cec5SDimitry Andric (BaseReg.getReg() == Mips::GP ||
21870b57cec5SDimitry Andric BaseReg.getReg() == Mips::GP_64)) {
21880b57cec5SDimitry Andric
21890b57cec5SDimitry Andric TOut.emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
21900b57cec5SDimitry Andric IDLoc, STI);
21910b57cec5SDimitry Andric return false;
21920b57cec5SDimitry Andric }
21930b57cec5SDimitry Andric }
21940b57cec5SDimitry Andric }
21950b57cec5SDimitry Andric } // for
21960b57cec5SDimitry Andric } // if load
21970b57cec5SDimitry Andric
21980b57cec5SDimitry Andric // TODO: Handle this with the AsmOperandClass.PredicateMethod.
21990b57cec5SDimitry Andric
22000b57cec5SDimitry Andric MCOperand Opnd;
22010b57cec5SDimitry Andric int Imm;
22020b57cec5SDimitry Andric
2203480093f4SDimitry Andric switch (Opcode) {
22040b57cec5SDimitry Andric default:
22050b57cec5SDimitry Andric break;
22060b57cec5SDimitry Andric case Mips::ADDIUSP_MM:
22070b57cec5SDimitry Andric Opnd = Inst.getOperand(0);
22080b57cec5SDimitry Andric if (!Opnd.isImm())
22090b57cec5SDimitry Andric return Error(IDLoc, "expected immediate operand kind");
22100b57cec5SDimitry Andric Imm = Opnd.getImm();
22110b57cec5SDimitry Andric if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
22120b57cec5SDimitry Andric Imm % 4 != 0)
22130b57cec5SDimitry Andric return Error(IDLoc, "immediate operand value out of range");
22140b57cec5SDimitry Andric break;
22150b57cec5SDimitry Andric case Mips::SLL16_MM:
22160b57cec5SDimitry Andric case Mips::SRL16_MM:
22170b57cec5SDimitry Andric Opnd = Inst.getOperand(2);
22180b57cec5SDimitry Andric if (!Opnd.isImm())
22190b57cec5SDimitry Andric return Error(IDLoc, "expected immediate operand kind");
22200b57cec5SDimitry Andric Imm = Opnd.getImm();
22210b57cec5SDimitry Andric if (Imm < 1 || Imm > 8)
22220b57cec5SDimitry Andric return Error(IDLoc, "immediate operand value out of range");
22230b57cec5SDimitry Andric break;
22240b57cec5SDimitry Andric case Mips::LI16_MM:
22250b57cec5SDimitry Andric Opnd = Inst.getOperand(1);
22260b57cec5SDimitry Andric if (!Opnd.isImm())
22270b57cec5SDimitry Andric return Error(IDLoc, "expected immediate operand kind");
22280b57cec5SDimitry Andric Imm = Opnd.getImm();
22290b57cec5SDimitry Andric if (Imm < -1 || Imm > 126)
22300b57cec5SDimitry Andric return Error(IDLoc, "immediate operand value out of range");
22310b57cec5SDimitry Andric break;
22320b57cec5SDimitry Andric case Mips::ADDIUR2_MM:
22330b57cec5SDimitry Andric Opnd = Inst.getOperand(2);
22340b57cec5SDimitry Andric if (!Opnd.isImm())
22350b57cec5SDimitry Andric return Error(IDLoc, "expected immediate operand kind");
22360b57cec5SDimitry Andric Imm = Opnd.getImm();
22370b57cec5SDimitry Andric if (!(Imm == 1 || Imm == -1 ||
22380b57cec5SDimitry Andric ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
22390b57cec5SDimitry Andric return Error(IDLoc, "immediate operand value out of range");
22400b57cec5SDimitry Andric break;
22410b57cec5SDimitry Andric case Mips::ANDI16_MM:
22420b57cec5SDimitry Andric Opnd = Inst.getOperand(2);
22430b57cec5SDimitry Andric if (!Opnd.isImm())
22440b57cec5SDimitry Andric return Error(IDLoc, "expected immediate operand kind");
22450b57cec5SDimitry Andric Imm = Opnd.getImm();
22460b57cec5SDimitry Andric if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
22470b57cec5SDimitry Andric Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
22480b57cec5SDimitry Andric Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
22490b57cec5SDimitry Andric return Error(IDLoc, "immediate operand value out of range");
22500b57cec5SDimitry Andric break;
22510b57cec5SDimitry Andric case Mips::LBU16_MM:
22520b57cec5SDimitry Andric Opnd = Inst.getOperand(2);
22530b57cec5SDimitry Andric if (!Opnd.isImm())
22540b57cec5SDimitry Andric return Error(IDLoc, "expected immediate operand kind");
22550b57cec5SDimitry Andric Imm = Opnd.getImm();
22560b57cec5SDimitry Andric if (Imm < -1 || Imm > 14)
22570b57cec5SDimitry Andric return Error(IDLoc, "immediate operand value out of range");
22580b57cec5SDimitry Andric break;
22590b57cec5SDimitry Andric case Mips::SB16_MM:
22600b57cec5SDimitry Andric case Mips::SB16_MMR6:
22610b57cec5SDimitry Andric Opnd = Inst.getOperand(2);
22620b57cec5SDimitry Andric if (!Opnd.isImm())
22630b57cec5SDimitry Andric return Error(IDLoc, "expected immediate operand kind");
22640b57cec5SDimitry Andric Imm = Opnd.getImm();
22650b57cec5SDimitry Andric if (Imm < 0 || Imm > 15)
22660b57cec5SDimitry Andric return Error(IDLoc, "immediate operand value out of range");
22670b57cec5SDimitry Andric break;
22680b57cec5SDimitry Andric case Mips::LHU16_MM:
22690b57cec5SDimitry Andric case Mips::SH16_MM:
22700b57cec5SDimitry Andric case Mips::SH16_MMR6:
22710b57cec5SDimitry Andric Opnd = Inst.getOperand(2);
22720b57cec5SDimitry Andric if (!Opnd.isImm())
22730b57cec5SDimitry Andric return Error(IDLoc, "expected immediate operand kind");
22740b57cec5SDimitry Andric Imm = Opnd.getImm();
22750b57cec5SDimitry Andric if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
22760b57cec5SDimitry Andric return Error(IDLoc, "immediate operand value out of range");
22770b57cec5SDimitry Andric break;
22780b57cec5SDimitry Andric case Mips::LW16_MM:
22790b57cec5SDimitry Andric case Mips::SW16_MM:
22800b57cec5SDimitry Andric case Mips::SW16_MMR6:
22810b57cec5SDimitry Andric Opnd = Inst.getOperand(2);
22820b57cec5SDimitry Andric if (!Opnd.isImm())
22830b57cec5SDimitry Andric return Error(IDLoc, "expected immediate operand kind");
22840b57cec5SDimitry Andric Imm = Opnd.getImm();
22850b57cec5SDimitry Andric if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
22860b57cec5SDimitry Andric return Error(IDLoc, "immediate operand value out of range");
22870b57cec5SDimitry Andric break;
22880b57cec5SDimitry Andric case Mips::ADDIUPC_MM:
22890b57cec5SDimitry Andric Opnd = Inst.getOperand(1);
22900b57cec5SDimitry Andric if (!Opnd.isImm())
22910b57cec5SDimitry Andric return Error(IDLoc, "expected immediate operand kind");
22920b57cec5SDimitry Andric Imm = Opnd.getImm();
22930b57cec5SDimitry Andric if ((Imm % 4 != 0) || !isInt<25>(Imm))
22940b57cec5SDimitry Andric return Error(IDLoc, "immediate operand value out of range");
22950b57cec5SDimitry Andric break;
22960b57cec5SDimitry Andric case Mips::LWP_MM:
22970b57cec5SDimitry Andric case Mips::SWP_MM:
22980b57cec5SDimitry Andric if (Inst.getOperand(0).getReg() == Mips::RA)
22990b57cec5SDimitry Andric return Error(IDLoc, "invalid operand for instruction");
23000b57cec5SDimitry Andric break;
23010b57cec5SDimitry Andric case Mips::MOVEP_MM:
23020b57cec5SDimitry Andric case Mips::MOVEP_MMR6: {
23030b57cec5SDimitry Andric unsigned R0 = Inst.getOperand(0).getReg();
23040b57cec5SDimitry Andric unsigned R1 = Inst.getOperand(1).getReg();
23050b57cec5SDimitry Andric bool RegPair = ((R0 == Mips::A1 && R1 == Mips::A2) ||
23060b57cec5SDimitry Andric (R0 == Mips::A1 && R1 == Mips::A3) ||
23070b57cec5SDimitry Andric (R0 == Mips::A2 && R1 == Mips::A3) ||
23080b57cec5SDimitry Andric (R0 == Mips::A0 && R1 == Mips::S5) ||
23090b57cec5SDimitry Andric (R0 == Mips::A0 && R1 == Mips::S6) ||
23100b57cec5SDimitry Andric (R0 == Mips::A0 && R1 == Mips::A1) ||
23110b57cec5SDimitry Andric (R0 == Mips::A0 && R1 == Mips::A2) ||
23120b57cec5SDimitry Andric (R0 == Mips::A0 && R1 == Mips::A3));
23130b57cec5SDimitry Andric if (!RegPair)
23140b57cec5SDimitry Andric return Error(IDLoc, "invalid operand for instruction");
23150b57cec5SDimitry Andric break;
23160b57cec5SDimitry Andric }
23170b57cec5SDimitry Andric }
23180b57cec5SDimitry Andric }
23190b57cec5SDimitry Andric
23200b57cec5SDimitry Andric bool FillDelaySlot =
23210b57cec5SDimitry Andric MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder();
23224c2d3b02SDimitry Andric
23234c2d3b02SDimitry Andric // Get previous instruction`s forbidden slot attribute and
23244c2d3b02SDimitry Andric // whether set reorder.
23254c2d3b02SDimitry Andric bool PrevForbiddenSlotAttr = CurForbiddenSlotAttr;
23264c2d3b02SDimitry Andric
23274c2d3b02SDimitry Andric // Flag represents we set reorder after nop.
23284c2d3b02SDimitry Andric bool SetReorderAfterNop = false;
23294c2d3b02SDimitry Andric
23304c2d3b02SDimitry Andric // If previous instruction has forbidden slot and .set reorder
23314c2d3b02SDimitry Andric // is active and current instruction is CTI.
23324c2d3b02SDimitry Andric // Then emit a NOP after it.
23334c2d3b02SDimitry Andric if (PrevForbiddenSlotAttr && !SafeInForbiddenSlot(MCID)) {
23344c2d3b02SDimitry Andric TOut.emitEmptyDelaySlot(false, IDLoc, STI);
23354c2d3b02SDimitry Andric // When 'FillDelaySlot' is true, the existing logic will add
23364c2d3b02SDimitry Andric // noreorder before instruction and reorder after it. So there
23374c2d3b02SDimitry Andric // need exclude this case avoiding two '.set reorder'.
23384c2d3b02SDimitry Andric // The format of the first case is:
23394c2d3b02SDimitry Andric // .set noreorder
23404c2d3b02SDimitry Andric // bnezc
23414c2d3b02SDimitry Andric // nop
23424c2d3b02SDimitry Andric // .set reorder
23434c2d3b02SDimitry Andric if (AssemblerOptions.back()->isReorder() && !FillDelaySlot) {
23444c2d3b02SDimitry Andric SetReorderAfterNop = true;
23454c2d3b02SDimitry Andric TOut.emitDirectiveSetReorder();
23464c2d3b02SDimitry Andric }
23474c2d3b02SDimitry Andric }
23484c2d3b02SDimitry Andric
23494c2d3b02SDimitry Andric // Save current instruction`s forbidden slot and whether set reorder.
23504c2d3b02SDimitry Andric // This is the judgment condition for whether to add nop.
23514c2d3b02SDimitry Andric // We would add a couple of '.set noreorder' and '.set reorder' to
23524c2d3b02SDimitry Andric // wrap the current instruction and the next instruction.
23534c2d3b02SDimitry Andric CurForbiddenSlotAttr =
23544c2d3b02SDimitry Andric hasForbiddenSlot(MCID) && AssemblerOptions.back()->isReorder();
23554c2d3b02SDimitry Andric
23564c2d3b02SDimitry Andric if (FillDelaySlot || CurForbiddenSlotAttr)
23570b57cec5SDimitry Andric TOut.emitDirectiveSetNoReorder();
23580b57cec5SDimitry Andric
23590b57cec5SDimitry Andric MacroExpanderResultTy ExpandResult =
23600b57cec5SDimitry Andric tryExpandInstruction(Inst, IDLoc, Out, STI);
23610b57cec5SDimitry Andric switch (ExpandResult) {
23620b57cec5SDimitry Andric case MER_NotAMacro:
23635ffd83dbSDimitry Andric Out.emitInstruction(Inst, *STI);
23640b57cec5SDimitry Andric break;
23650b57cec5SDimitry Andric case MER_Success:
23660b57cec5SDimitry Andric break;
23670b57cec5SDimitry Andric case MER_Fail:
23680b57cec5SDimitry Andric return true;
23690b57cec5SDimitry Andric }
23700b57cec5SDimitry Andric
23714c2d3b02SDimitry Andric // When current instruction was not CTI, recover reorder state.
23724c2d3b02SDimitry Andric // The format of the second case is:
23734c2d3b02SDimitry Andric // .set noreoder
23744c2d3b02SDimitry Andric // bnezc
23754c2d3b02SDimitry Andric // add
23764c2d3b02SDimitry Andric // .set reorder
23774c2d3b02SDimitry Andric if (PrevForbiddenSlotAttr && !SetReorderAfterNop && !FillDelaySlot &&
23784c2d3b02SDimitry Andric AssemblerOptions.back()->isReorder()) {
23794c2d3b02SDimitry Andric TOut.emitDirectiveSetReorder();
23804c2d3b02SDimitry Andric }
23814c2d3b02SDimitry Andric
23820b57cec5SDimitry Andric // We know we emitted an instruction on the MER_NotAMacro or MER_Success path.
23830b57cec5SDimitry Andric // If we're in microMIPS mode then we must also set EF_MIPS_MICROMIPS.
23840b57cec5SDimitry Andric if (inMicroMipsMode()) {
23850b57cec5SDimitry Andric TOut.setUsesMicroMips();
23860b57cec5SDimitry Andric TOut.updateABIInfo(*this);
23870b57cec5SDimitry Andric }
23880b57cec5SDimitry Andric
23890b57cec5SDimitry Andric // If this instruction has a delay slot and .set reorder is active,
23900b57cec5SDimitry Andric // emit a NOP after it.
23914c2d3b02SDimitry Andric // The format of the third case is:
23924c2d3b02SDimitry Andric // .set noreorder
23934c2d3b02SDimitry Andric // bnezc
23944c2d3b02SDimitry Andric // nop
23954c2d3b02SDimitry Andric // .set noreorder
23964c2d3b02SDimitry Andric // j
23974c2d3b02SDimitry Andric // nop
23984c2d3b02SDimitry Andric // .set reorder
23990b57cec5SDimitry Andric if (FillDelaySlot) {
24000b57cec5SDimitry Andric TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst), IDLoc, STI);
24010b57cec5SDimitry Andric TOut.emitDirectiveSetReorder();
24020b57cec5SDimitry Andric }
24030b57cec5SDimitry Andric
2404480093f4SDimitry Andric if ((Opcode == Mips::JalOneReg || Opcode == Mips::JalTwoReg ||
2405480093f4SDimitry Andric ExpandedJalSym) &&
24060b57cec5SDimitry Andric isPicAndNotNxxAbi()) {
24070b57cec5SDimitry Andric if (IsCpRestoreSet) {
24080b57cec5SDimitry Andric // We need a NOP between the JALR and the LW:
24090b57cec5SDimitry Andric // If .set reorder has been used, we've already emitted a NOP.
24100b57cec5SDimitry Andric // If .set noreorder has been used, we need to emit a NOP at this point.
24110b57cec5SDimitry Andric if (!AssemblerOptions.back()->isReorder())
24120b57cec5SDimitry Andric TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst), IDLoc,
24130b57cec5SDimitry Andric STI);
24140b57cec5SDimitry Andric
24150b57cec5SDimitry Andric // Load the $gp from the stack.
24160b57cec5SDimitry Andric TOut.emitGPRestore(CpRestoreOffset, IDLoc, STI);
24170b57cec5SDimitry Andric } else
24180b57cec5SDimitry Andric Warning(IDLoc, "no .cprestore used in PIC mode");
24190b57cec5SDimitry Andric }
24200b57cec5SDimitry Andric
24210b57cec5SDimitry Andric return false;
24220b57cec5SDimitry Andric }
24230b57cec5SDimitry Andric
onEndOfFile()24244c2d3b02SDimitry Andric void MipsAsmParser::onEndOfFile() {
24254c2d3b02SDimitry Andric MipsTargetStreamer &TOut = getTargetStreamer();
24264c2d3b02SDimitry Andric SMLoc IDLoc = SMLoc();
24274c2d3b02SDimitry Andric // If has pending forbidden slot, fill nop and recover reorder.
24284c2d3b02SDimitry Andric if (CurForbiddenSlotAttr) {
24294c2d3b02SDimitry Andric TOut.emitEmptyDelaySlot(false, IDLoc, STI);
24304c2d3b02SDimitry Andric if (AssemblerOptions.back()->isReorder())
24314c2d3b02SDimitry Andric TOut.emitDirectiveSetReorder();
24324c2d3b02SDimitry Andric }
24334c2d3b02SDimitry Andric }
24344c2d3b02SDimitry Andric
24350b57cec5SDimitry Andric MipsAsmParser::MacroExpanderResultTy
tryExpandInstruction(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)24360b57cec5SDimitry Andric MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
24370b57cec5SDimitry Andric const MCSubtargetInfo *STI) {
24380b57cec5SDimitry Andric switch (Inst.getOpcode()) {
24390b57cec5SDimitry Andric default:
24400b57cec5SDimitry Andric return MER_NotAMacro;
24410b57cec5SDimitry Andric case Mips::LoadImm32:
24420b57cec5SDimitry Andric return expandLoadImm(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
24430b57cec5SDimitry Andric case Mips::LoadImm64:
24440b57cec5SDimitry Andric return expandLoadImm(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
24450b57cec5SDimitry Andric case Mips::LoadAddrImm32:
24460b57cec5SDimitry Andric case Mips::LoadAddrImm64:
24470b57cec5SDimitry Andric assert(Inst.getOperand(0).isReg() && "expected register operand kind");
24480b57cec5SDimitry Andric assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
24490b57cec5SDimitry Andric "expected immediate operand kind");
24500b57cec5SDimitry Andric
24510b57cec5SDimitry Andric return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,
24520b57cec5SDimitry Andric Inst.getOperand(1),
24530b57cec5SDimitry Andric Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,
24540b57cec5SDimitry Andric Out, STI)
24550b57cec5SDimitry Andric ? MER_Fail
24560b57cec5SDimitry Andric : MER_Success;
24570b57cec5SDimitry Andric case Mips::LoadAddrReg32:
24580b57cec5SDimitry Andric case Mips::LoadAddrReg64:
24590b57cec5SDimitry Andric assert(Inst.getOperand(0).isReg() && "expected register operand kind");
24600b57cec5SDimitry Andric assert(Inst.getOperand(1).isReg() && "expected register operand kind");
24610b57cec5SDimitry Andric assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
24620b57cec5SDimitry Andric "expected immediate operand kind");
24630b57cec5SDimitry Andric
24640b57cec5SDimitry Andric return expandLoadAddress(Inst.getOperand(0).getReg(),
24650b57cec5SDimitry Andric Inst.getOperand(1).getReg(), Inst.getOperand(2),
24660b57cec5SDimitry Andric Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,
24670b57cec5SDimitry Andric Out, STI)
24680b57cec5SDimitry Andric ? MER_Fail
24690b57cec5SDimitry Andric : MER_Success;
24700b57cec5SDimitry Andric case Mips::B_MM_Pseudo:
24710b57cec5SDimitry Andric case Mips::B_MMR6_Pseudo:
24720b57cec5SDimitry Andric return expandUncondBranchMMPseudo(Inst, IDLoc, Out, STI) ? MER_Fail
24730b57cec5SDimitry Andric : MER_Success;
24740b57cec5SDimitry Andric case Mips::SWM_MM:
24750b57cec5SDimitry Andric case Mips::LWM_MM:
24760b57cec5SDimitry Andric return expandLoadStoreMultiple(Inst, IDLoc, Out, STI) ? MER_Fail
24770b57cec5SDimitry Andric : MER_Success;
24780b57cec5SDimitry Andric case Mips::JalOneReg:
24790b57cec5SDimitry Andric case Mips::JalTwoReg:
24800b57cec5SDimitry Andric return expandJalWithRegs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
24810b57cec5SDimitry Andric case Mips::BneImm:
24820b57cec5SDimitry Andric case Mips::BeqImm:
24830b57cec5SDimitry Andric case Mips::BEQLImmMacro:
24840b57cec5SDimitry Andric case Mips::BNELImmMacro:
24850b57cec5SDimitry Andric return expandBranchImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
24860b57cec5SDimitry Andric case Mips::BLT:
24870b57cec5SDimitry Andric case Mips::BLE:
24880b57cec5SDimitry Andric case Mips::BGE:
24890b57cec5SDimitry Andric case Mips::BGT:
24900b57cec5SDimitry Andric case Mips::BLTU:
24910b57cec5SDimitry Andric case Mips::BLEU:
24920b57cec5SDimitry Andric case Mips::BGEU:
24930b57cec5SDimitry Andric case Mips::BGTU:
24940b57cec5SDimitry Andric case Mips::BLTL:
24950b57cec5SDimitry Andric case Mips::BLEL:
24960b57cec5SDimitry Andric case Mips::BGEL:
24970b57cec5SDimitry Andric case Mips::BGTL:
24980b57cec5SDimitry Andric case Mips::BLTUL:
24990b57cec5SDimitry Andric case Mips::BLEUL:
25000b57cec5SDimitry Andric case Mips::BGEUL:
25010b57cec5SDimitry Andric case Mips::BGTUL:
25020b57cec5SDimitry Andric case Mips::BLTImmMacro:
25030b57cec5SDimitry Andric case Mips::BLEImmMacro:
25040b57cec5SDimitry Andric case Mips::BGEImmMacro:
25050b57cec5SDimitry Andric case Mips::BGTImmMacro:
25060b57cec5SDimitry Andric case Mips::BLTUImmMacro:
25070b57cec5SDimitry Andric case Mips::BLEUImmMacro:
25080b57cec5SDimitry Andric case Mips::BGEUImmMacro:
25090b57cec5SDimitry Andric case Mips::BGTUImmMacro:
25100b57cec5SDimitry Andric case Mips::BLTLImmMacro:
25110b57cec5SDimitry Andric case Mips::BLELImmMacro:
25120b57cec5SDimitry Andric case Mips::BGELImmMacro:
25130b57cec5SDimitry Andric case Mips::BGTLImmMacro:
25140b57cec5SDimitry Andric case Mips::BLTULImmMacro:
25150b57cec5SDimitry Andric case Mips::BLEULImmMacro:
25160b57cec5SDimitry Andric case Mips::BGEULImmMacro:
25170b57cec5SDimitry Andric case Mips::BGTULImmMacro:
25180b57cec5SDimitry Andric return expandCondBranches(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
25190b57cec5SDimitry Andric case Mips::SDivMacro:
25200b57cec5SDimitry Andric case Mips::SDivIMacro:
25210b57cec5SDimitry Andric case Mips::SRemMacro:
25220b57cec5SDimitry Andric case Mips::SRemIMacro:
25230b57cec5SDimitry Andric return expandDivRem(Inst, IDLoc, Out, STI, false, true) ? MER_Fail
25240b57cec5SDimitry Andric : MER_Success;
25250b57cec5SDimitry Andric case Mips::DSDivMacro:
25260b57cec5SDimitry Andric case Mips::DSDivIMacro:
25270b57cec5SDimitry Andric case Mips::DSRemMacro:
25280b57cec5SDimitry Andric case Mips::DSRemIMacro:
25290b57cec5SDimitry Andric return expandDivRem(Inst, IDLoc, Out, STI, true, true) ? MER_Fail
25300b57cec5SDimitry Andric : MER_Success;
25310b57cec5SDimitry Andric case Mips::UDivMacro:
25320b57cec5SDimitry Andric case Mips::UDivIMacro:
25330b57cec5SDimitry Andric case Mips::URemMacro:
25340b57cec5SDimitry Andric case Mips::URemIMacro:
25350b57cec5SDimitry Andric return expandDivRem(Inst, IDLoc, Out, STI, false, false) ? MER_Fail
25360b57cec5SDimitry Andric : MER_Success;
25370b57cec5SDimitry Andric case Mips::DUDivMacro:
25380b57cec5SDimitry Andric case Mips::DUDivIMacro:
25390b57cec5SDimitry Andric case Mips::DURemMacro:
25400b57cec5SDimitry Andric case Mips::DURemIMacro:
25410b57cec5SDimitry Andric return expandDivRem(Inst, IDLoc, Out, STI, true, false) ? MER_Fail
25420b57cec5SDimitry Andric : MER_Success;
25430b57cec5SDimitry Andric case Mips::PseudoTRUNC_W_S:
25440b57cec5SDimitry Andric return expandTrunc(Inst, false, false, IDLoc, Out, STI) ? MER_Fail
25450b57cec5SDimitry Andric : MER_Success;
25460b57cec5SDimitry Andric case Mips::PseudoTRUNC_W_D32:
25470b57cec5SDimitry Andric return expandTrunc(Inst, true, false, IDLoc, Out, STI) ? MER_Fail
25480b57cec5SDimitry Andric : MER_Success;
25490b57cec5SDimitry Andric case Mips::PseudoTRUNC_W_D:
25500b57cec5SDimitry Andric return expandTrunc(Inst, true, true, IDLoc, Out, STI) ? MER_Fail
25510b57cec5SDimitry Andric : MER_Success;
25520b57cec5SDimitry Andric
25530b57cec5SDimitry Andric case Mips::LoadImmSingleGPR:
2554c14a5a88SDimitry Andric return expandLoadSingleImmToGPR(Inst, IDLoc, Out, STI) ? MER_Fail
25550b57cec5SDimitry Andric : MER_Success;
25560b57cec5SDimitry Andric case Mips::LoadImmSingleFGR:
2557c14a5a88SDimitry Andric return expandLoadSingleImmToFPR(Inst, IDLoc, Out, STI) ? MER_Fail
25580b57cec5SDimitry Andric : MER_Success;
25590b57cec5SDimitry Andric case Mips::LoadImmDoubleGPR:
2560c14a5a88SDimitry Andric return expandLoadDoubleImmToGPR(Inst, IDLoc, Out, STI) ? MER_Fail
25610b57cec5SDimitry Andric : MER_Success;
25620b57cec5SDimitry Andric case Mips::LoadImmDoubleFGR:
2563c14a5a88SDimitry Andric return expandLoadDoubleImmToFPR(Inst, true, IDLoc, Out, STI) ? MER_Fail
25640b57cec5SDimitry Andric : MER_Success;
25650b57cec5SDimitry Andric case Mips::LoadImmDoubleFGR_32:
2566c14a5a88SDimitry Andric return expandLoadDoubleImmToFPR(Inst, false, IDLoc, Out, STI) ? MER_Fail
25670b57cec5SDimitry Andric : MER_Success;
2568c14a5a88SDimitry Andric
25690b57cec5SDimitry Andric case Mips::Ulh:
25700b57cec5SDimitry Andric return expandUlh(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
25710b57cec5SDimitry Andric case Mips::Ulhu:
25720b57cec5SDimitry Andric return expandUlh(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
25730b57cec5SDimitry Andric case Mips::Ush:
25740b57cec5SDimitry Andric return expandUsh(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
25750b57cec5SDimitry Andric case Mips::Ulw:
25760b57cec5SDimitry Andric case Mips::Usw:
25770b57cec5SDimitry Andric return expandUxw(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
25780b57cec5SDimitry Andric case Mips::NORImm:
25790b57cec5SDimitry Andric case Mips::NORImm64:
25800b57cec5SDimitry Andric return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
25810b57cec5SDimitry Andric case Mips::SGE:
25820b57cec5SDimitry Andric case Mips::SGEU:
25830b57cec5SDimitry Andric return expandSge(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
25840b57cec5SDimitry Andric case Mips::SGEImm:
25850b57cec5SDimitry Andric case Mips::SGEUImm:
25860b57cec5SDimitry Andric case Mips::SGEImm64:
25870b57cec5SDimitry Andric case Mips::SGEUImm64:
25880b57cec5SDimitry Andric return expandSgeImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
25890b57cec5SDimitry Andric case Mips::SGTImm:
25900b57cec5SDimitry Andric case Mips::SGTUImm:
25910b57cec5SDimitry Andric case Mips::SGTImm64:
25920b57cec5SDimitry Andric case Mips::SGTUImm64:
25930b57cec5SDimitry Andric return expandSgtImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
25945ffd83dbSDimitry Andric case Mips::SLE:
25955ffd83dbSDimitry Andric case Mips::SLEU:
25965ffd83dbSDimitry Andric return expandSle(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
25975ffd83dbSDimitry Andric case Mips::SLEImm:
25985ffd83dbSDimitry Andric case Mips::SLEUImm:
25995ffd83dbSDimitry Andric case Mips::SLEImm64:
26005ffd83dbSDimitry Andric case Mips::SLEUImm64:
26015ffd83dbSDimitry Andric return expandSleImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
26020b57cec5SDimitry Andric case Mips::SLTImm64:
26030b57cec5SDimitry Andric if (isInt<16>(Inst.getOperand(2).getImm())) {
26040b57cec5SDimitry Andric Inst.setOpcode(Mips::SLTi64);
26050b57cec5SDimitry Andric return MER_NotAMacro;
26060b57cec5SDimitry Andric }
26070b57cec5SDimitry Andric return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
26080b57cec5SDimitry Andric case Mips::SLTUImm64:
26090b57cec5SDimitry Andric if (isInt<16>(Inst.getOperand(2).getImm())) {
26100b57cec5SDimitry Andric Inst.setOpcode(Mips::SLTiu64);
26110b57cec5SDimitry Andric return MER_NotAMacro;
26120b57cec5SDimitry Andric }
26130b57cec5SDimitry Andric return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
26140b57cec5SDimitry Andric case Mips::ADDi: case Mips::ADDi_MM:
26150b57cec5SDimitry Andric case Mips::ADDiu: case Mips::ADDiu_MM:
26160b57cec5SDimitry Andric case Mips::SLTi: case Mips::SLTi_MM:
26170b57cec5SDimitry Andric case Mips::SLTiu: case Mips::SLTiu_MM:
26180b57cec5SDimitry Andric if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
26190b57cec5SDimitry Andric Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
26200b57cec5SDimitry Andric int64_t ImmValue = Inst.getOperand(2).getImm();
26210b57cec5SDimitry Andric if (isInt<16>(ImmValue))
26220b57cec5SDimitry Andric return MER_NotAMacro;
26230b57cec5SDimitry Andric return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
26240b57cec5SDimitry Andric : MER_Success;
26250b57cec5SDimitry Andric }
26260b57cec5SDimitry Andric return MER_NotAMacro;
26270b57cec5SDimitry Andric case Mips::ANDi: case Mips::ANDi_MM: case Mips::ANDi64:
26280b57cec5SDimitry Andric case Mips::ORi: case Mips::ORi_MM: case Mips::ORi64:
26290b57cec5SDimitry Andric case Mips::XORi: case Mips::XORi_MM: case Mips::XORi64:
26300b57cec5SDimitry Andric if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
26310b57cec5SDimitry Andric Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
26320b57cec5SDimitry Andric int64_t ImmValue = Inst.getOperand(2).getImm();
26330b57cec5SDimitry Andric if (isUInt<16>(ImmValue))
26340b57cec5SDimitry Andric return MER_NotAMacro;
26350b57cec5SDimitry Andric return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
26360b57cec5SDimitry Andric : MER_Success;
26370b57cec5SDimitry Andric }
26380b57cec5SDimitry Andric return MER_NotAMacro;
26390b57cec5SDimitry Andric case Mips::ROL:
26400b57cec5SDimitry Andric case Mips::ROR:
26410b57cec5SDimitry Andric return expandRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
26420b57cec5SDimitry Andric case Mips::ROLImm:
26430b57cec5SDimitry Andric case Mips::RORImm:
26440b57cec5SDimitry Andric return expandRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
26450b57cec5SDimitry Andric case Mips::DROL:
26460b57cec5SDimitry Andric case Mips::DROR:
26470b57cec5SDimitry Andric return expandDRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
26480b57cec5SDimitry Andric case Mips::DROLImm:
26490b57cec5SDimitry Andric case Mips::DRORImm:
26500b57cec5SDimitry Andric return expandDRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
26510b57cec5SDimitry Andric case Mips::ABSMacro:
26520b57cec5SDimitry Andric return expandAbs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
26530b57cec5SDimitry Andric case Mips::MULImmMacro:
26540b57cec5SDimitry Andric case Mips::DMULImmMacro:
26550b57cec5SDimitry Andric return expandMulImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
26560b57cec5SDimitry Andric case Mips::MULOMacro:
26570b57cec5SDimitry Andric case Mips::DMULOMacro:
26580b57cec5SDimitry Andric return expandMulO(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
26590b57cec5SDimitry Andric case Mips::MULOUMacro:
26600b57cec5SDimitry Andric case Mips::DMULOUMacro:
26610b57cec5SDimitry Andric return expandMulOU(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
26620b57cec5SDimitry Andric case Mips::DMULMacro:
26630b57cec5SDimitry Andric return expandDMULMacro(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
26640b57cec5SDimitry Andric case Mips::LDMacro:
26650b57cec5SDimitry Andric case Mips::SDMacro:
26660b57cec5SDimitry Andric return expandLoadStoreDMacro(Inst, IDLoc, Out, STI,
26670b57cec5SDimitry Andric Inst.getOpcode() == Mips::LDMacro)
26680b57cec5SDimitry Andric ? MER_Fail
26690b57cec5SDimitry Andric : MER_Success;
26700b57cec5SDimitry Andric case Mips::SDC1_M1:
26710b57cec5SDimitry Andric return expandStoreDM1Macro(Inst, IDLoc, Out, STI)
26720b57cec5SDimitry Andric ? MER_Fail
26730b57cec5SDimitry Andric : MER_Success;
26740b57cec5SDimitry Andric case Mips::SEQMacro:
26750b57cec5SDimitry Andric return expandSeq(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
26760b57cec5SDimitry Andric case Mips::SEQIMacro:
26770b57cec5SDimitry Andric return expandSeqI(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
26785ffd83dbSDimitry Andric case Mips::SNEMacro:
26795ffd83dbSDimitry Andric return expandSne(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
26805ffd83dbSDimitry Andric case Mips::SNEIMacro:
26815ffd83dbSDimitry Andric return expandSneI(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
26820b57cec5SDimitry Andric case Mips::MFTC0: case Mips::MTTC0:
26830b57cec5SDimitry Andric case Mips::MFTGPR: case Mips::MTTGPR:
26840b57cec5SDimitry Andric case Mips::MFTLO: case Mips::MTTLO:
26850b57cec5SDimitry Andric case Mips::MFTHI: case Mips::MTTHI:
26860b57cec5SDimitry Andric case Mips::MFTACX: case Mips::MTTACX:
26870b57cec5SDimitry Andric case Mips::MFTDSP: case Mips::MTTDSP:
26880b57cec5SDimitry Andric case Mips::MFTC1: case Mips::MTTC1:
26890b57cec5SDimitry Andric case Mips::MFTHC1: case Mips::MTTHC1:
26900b57cec5SDimitry Andric case Mips::CFTC1: case Mips::CTTC1:
26910b57cec5SDimitry Andric return expandMXTRAlias(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
26920b57cec5SDimitry Andric case Mips::SaaAddr:
26930b57cec5SDimitry Andric case Mips::SaadAddr:
26940b57cec5SDimitry Andric return expandSaaAddr(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
26950b57cec5SDimitry Andric }
26960b57cec5SDimitry Andric }
26970b57cec5SDimitry Andric
expandJalWithRegs(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)26980b57cec5SDimitry Andric bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
26990b57cec5SDimitry Andric MCStreamer &Out,
27000b57cec5SDimitry Andric const MCSubtargetInfo *STI) {
27010b57cec5SDimitry Andric MipsTargetStreamer &TOut = getTargetStreamer();
27020b57cec5SDimitry Andric
27030b57cec5SDimitry Andric // Create a JALR instruction which is going to replace the pseudo-JAL.
27040b57cec5SDimitry Andric MCInst JalrInst;
27050b57cec5SDimitry Andric JalrInst.setLoc(IDLoc);
27060b57cec5SDimitry Andric const MCOperand FirstRegOp = Inst.getOperand(0);
27070b57cec5SDimitry Andric const unsigned Opcode = Inst.getOpcode();
27080b57cec5SDimitry Andric
27090b57cec5SDimitry Andric if (Opcode == Mips::JalOneReg) {
27100b57cec5SDimitry Andric // jal $rs => jalr $rs
27110b57cec5SDimitry Andric if (IsCpRestoreSet && inMicroMipsMode()) {
27120b57cec5SDimitry Andric JalrInst.setOpcode(Mips::JALRS16_MM);
27130b57cec5SDimitry Andric JalrInst.addOperand(FirstRegOp);
27140b57cec5SDimitry Andric } else if (inMicroMipsMode()) {
27150b57cec5SDimitry Andric JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
27160b57cec5SDimitry Andric JalrInst.addOperand(FirstRegOp);
27170b57cec5SDimitry Andric } else {
27180b57cec5SDimitry Andric JalrInst.setOpcode(Mips::JALR);
27190b57cec5SDimitry Andric JalrInst.addOperand(MCOperand::createReg(Mips::RA));
27200b57cec5SDimitry Andric JalrInst.addOperand(FirstRegOp);
27210b57cec5SDimitry Andric }
27220b57cec5SDimitry Andric } else if (Opcode == Mips::JalTwoReg) {
27230b57cec5SDimitry Andric // jal $rd, $rs => jalr $rd, $rs
27240b57cec5SDimitry Andric if (IsCpRestoreSet && inMicroMipsMode())
27250b57cec5SDimitry Andric JalrInst.setOpcode(Mips::JALRS_MM);
27260b57cec5SDimitry Andric else
27270b57cec5SDimitry Andric JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
27280b57cec5SDimitry Andric JalrInst.addOperand(FirstRegOp);
27290b57cec5SDimitry Andric const MCOperand SecondRegOp = Inst.getOperand(1);
27300b57cec5SDimitry Andric JalrInst.addOperand(SecondRegOp);
27310b57cec5SDimitry Andric }
27325ffd83dbSDimitry Andric Out.emitInstruction(JalrInst, *STI);
27330b57cec5SDimitry Andric
27340b57cec5SDimitry Andric // If .set reorder is active and branch instruction has a delay slot,
27350b57cec5SDimitry Andric // emit a NOP after it.
2736bdd1243dSDimitry Andric const MCInstrDesc &MCID = MII.get(JalrInst.getOpcode());
27370b57cec5SDimitry Andric if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
27380b57cec5SDimitry Andric TOut.emitEmptyDelaySlot(hasShortDelaySlot(JalrInst), IDLoc,
27390b57cec5SDimitry Andric STI);
27400b57cec5SDimitry Andric
27410b57cec5SDimitry Andric return false;
27420b57cec5SDimitry Andric }
27430b57cec5SDimitry Andric
27440b57cec5SDimitry Andric /// Can the value be represented by a unsigned N-bit value and a shift left?
isShiftedUIntAtAnyPosition(uint64_t x)27450b57cec5SDimitry Andric template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
274606c3fb27SDimitry Andric return x && isUInt<N>(x >> llvm::countr_zero(x));
27470b57cec5SDimitry Andric }
27480b57cec5SDimitry Andric
27490b57cec5SDimitry Andric /// Load (or add) an immediate into a register.
27500b57cec5SDimitry Andric ///
27510b57cec5SDimitry Andric /// @param ImmValue The immediate to load.
27520b57cec5SDimitry Andric /// @param DstReg The register that will hold the immediate.
27530b57cec5SDimitry Andric /// @param SrcReg A register to add to the immediate or Mips::NoRegister
27540b57cec5SDimitry Andric /// for a simple initialization.
27550b57cec5SDimitry Andric /// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
27560b57cec5SDimitry Andric /// @param IsAddress True if the immediate represents an address. False if it
27570b57cec5SDimitry Andric /// is an integer.
27580b57cec5SDimitry Andric /// @param IDLoc Location of the immediate in the source file.
loadImmediate(int64_t ImmValue,unsigned DstReg,unsigned SrcReg,bool Is32BitImm,bool IsAddress,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)27590b57cec5SDimitry Andric bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
27600b57cec5SDimitry Andric unsigned SrcReg, bool Is32BitImm,
27610b57cec5SDimitry Andric bool IsAddress, SMLoc IDLoc, MCStreamer &Out,
27620b57cec5SDimitry Andric const MCSubtargetInfo *STI) {
27630b57cec5SDimitry Andric MipsTargetStreamer &TOut = getTargetStreamer();
27640b57cec5SDimitry Andric
27650b57cec5SDimitry Andric if (!Is32BitImm && !isGP64bit()) {
27660b57cec5SDimitry Andric Error(IDLoc, "instruction requires a 64-bit architecture");
27670b57cec5SDimitry Andric return true;
27680b57cec5SDimitry Andric }
27690b57cec5SDimitry Andric
27700b57cec5SDimitry Andric if (Is32BitImm) {
27710b57cec5SDimitry Andric if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
27720b57cec5SDimitry Andric // Sign extend up to 64-bit so that the predicates match the hardware
27730b57cec5SDimitry Andric // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
27740b57cec5SDimitry Andric // true.
27750b57cec5SDimitry Andric ImmValue = SignExtend64<32>(ImmValue);
27760b57cec5SDimitry Andric } else {
27770b57cec5SDimitry Andric Error(IDLoc, "instruction requires a 32-bit immediate");
27780b57cec5SDimitry Andric return true;
27790b57cec5SDimitry Andric }
27800b57cec5SDimitry Andric }
27810b57cec5SDimitry Andric
27820b57cec5SDimitry Andric unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
27830b57cec5SDimitry Andric unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
27840b57cec5SDimitry Andric
27850b57cec5SDimitry Andric bool UseSrcReg = false;
27860b57cec5SDimitry Andric if (SrcReg != Mips::NoRegister)
27870b57cec5SDimitry Andric UseSrcReg = true;
27880b57cec5SDimitry Andric
27890b57cec5SDimitry Andric unsigned TmpReg = DstReg;
27900b57cec5SDimitry Andric if (UseSrcReg &&
27910b57cec5SDimitry Andric getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
27920b57cec5SDimitry Andric // At this point we need AT to perform the expansions and we exit if it is
27930b57cec5SDimitry Andric // not available.
27940b57cec5SDimitry Andric unsigned ATReg = getATReg(IDLoc);
27950b57cec5SDimitry Andric if (!ATReg)
27960b57cec5SDimitry Andric return true;
27970b57cec5SDimitry Andric TmpReg = ATReg;
27980b57cec5SDimitry Andric }
27990b57cec5SDimitry Andric
28000b57cec5SDimitry Andric if (isInt<16>(ImmValue)) {
28010b57cec5SDimitry Andric if (!UseSrcReg)
28020b57cec5SDimitry Andric SrcReg = ZeroReg;
28030b57cec5SDimitry Andric
28040b57cec5SDimitry Andric // This doesn't quite follow the usual ABI expectations for N32 but matches
28050b57cec5SDimitry Andric // traditional assembler behaviour. N32 would normally use addiu for both
28060b57cec5SDimitry Andric // integers and addresses.
28070b57cec5SDimitry Andric if (IsAddress && !Is32BitImm) {
28080b57cec5SDimitry Andric TOut.emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
28090b57cec5SDimitry Andric return false;
28100b57cec5SDimitry Andric }
28110b57cec5SDimitry Andric
28120b57cec5SDimitry Andric TOut.emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
28130b57cec5SDimitry Andric return false;
28140b57cec5SDimitry Andric }
28150b57cec5SDimitry Andric
28160b57cec5SDimitry Andric if (isUInt<16>(ImmValue)) {
28170b57cec5SDimitry Andric unsigned TmpReg = DstReg;
28180b57cec5SDimitry Andric if (SrcReg == DstReg) {
28190b57cec5SDimitry Andric TmpReg = getATReg(IDLoc);
28200b57cec5SDimitry Andric if (!TmpReg)
28210b57cec5SDimitry Andric return true;
28220b57cec5SDimitry Andric }
28230b57cec5SDimitry Andric
28240b57cec5SDimitry Andric TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, STI);
28250b57cec5SDimitry Andric if (UseSrcReg)
28260b57cec5SDimitry Andric TOut.emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, STI);
28270b57cec5SDimitry Andric return false;
28280b57cec5SDimitry Andric }
28290b57cec5SDimitry Andric
28300b57cec5SDimitry Andric if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
28310b57cec5SDimitry Andric warnIfNoMacro(IDLoc);
28320b57cec5SDimitry Andric
28330b57cec5SDimitry Andric uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
28340b57cec5SDimitry Andric uint16_t Bits15To0 = ImmValue & 0xffff;
28350b57cec5SDimitry Andric if (!Is32BitImm && !isInt<32>(ImmValue)) {
28360b57cec5SDimitry Andric // Traditional behaviour seems to special case this particular value. It's
28370b57cec5SDimitry Andric // not clear why other masks are handled differently.
28380b57cec5SDimitry Andric if (ImmValue == 0xffffffff) {
28390b57cec5SDimitry Andric TOut.emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, STI);
28400b57cec5SDimitry Andric TOut.emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, STI);
28410b57cec5SDimitry Andric if (UseSrcReg)
28420b57cec5SDimitry Andric TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
28430b57cec5SDimitry Andric return false;
28440b57cec5SDimitry Andric }
28450b57cec5SDimitry Andric
28460b57cec5SDimitry Andric // Expand to an ORi instead of a LUi to avoid sign-extending into the
28470b57cec5SDimitry Andric // upper 32 bits.
28480b57cec5SDimitry Andric TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, STI);
28490b57cec5SDimitry Andric TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI);
28500b57cec5SDimitry Andric if (Bits15To0)
28510b57cec5SDimitry Andric TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
28520b57cec5SDimitry Andric if (UseSrcReg)
28530b57cec5SDimitry Andric TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
28540b57cec5SDimitry Andric return false;
28550b57cec5SDimitry Andric }
28560b57cec5SDimitry Andric
28570b57cec5SDimitry Andric TOut.emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, STI);
28580b57cec5SDimitry Andric if (Bits15To0)
28590b57cec5SDimitry Andric TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
28600b57cec5SDimitry Andric if (UseSrcReg)
28610b57cec5SDimitry Andric TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
28620b57cec5SDimitry Andric return false;
28630b57cec5SDimitry Andric }
28640b57cec5SDimitry Andric
28650b57cec5SDimitry Andric if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
28660b57cec5SDimitry Andric if (Is32BitImm) {
28670b57cec5SDimitry Andric Error(IDLoc, "instruction requires a 32-bit immediate");
28680b57cec5SDimitry Andric return true;
28690b57cec5SDimitry Andric }
28700b57cec5SDimitry Andric
287106c3fb27SDimitry Andric // We've processed ImmValue satisfying isUInt<16> above, so ImmValue must be
287206c3fb27SDimitry Andric // at least 17-bit wide here.
287306c3fb27SDimitry Andric unsigned BitWidth = llvm::bit_width((uint64_t)ImmValue);
287406c3fb27SDimitry Andric assert(BitWidth >= 17 && "ImmValue must be at least 17-bit wide");
287506c3fb27SDimitry Andric
28760b57cec5SDimitry Andric // Traditionally, these immediates are shifted as little as possible and as
28770b57cec5SDimitry Andric // such we align the most significant bit to bit 15 of our temporary.
287806c3fb27SDimitry Andric unsigned ShiftAmount = BitWidth - 16;
28790b57cec5SDimitry Andric uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
28800b57cec5SDimitry Andric TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, STI);
28810b57cec5SDimitry Andric TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, STI);
28820b57cec5SDimitry Andric
28830b57cec5SDimitry Andric if (UseSrcReg)
28840b57cec5SDimitry Andric TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
28850b57cec5SDimitry Andric
28860b57cec5SDimitry Andric return false;
28870b57cec5SDimitry Andric }
28880b57cec5SDimitry Andric
28890b57cec5SDimitry Andric warnIfNoMacro(IDLoc);
28900b57cec5SDimitry Andric
28910b57cec5SDimitry Andric // The remaining case is packed with a sequence of dsll and ori with zeros
28920b57cec5SDimitry Andric // being omitted and any neighbouring dsll's being coalesced.
28930b57cec5SDimitry Andric // The highest 32-bit's are equivalent to a 32-bit immediate load.
28940b57cec5SDimitry Andric
28950b57cec5SDimitry Andric // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
28960b57cec5SDimitry Andric if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
28970b57cec5SDimitry Andric IDLoc, Out, STI))
28980b57cec5SDimitry Andric return false;
28990b57cec5SDimitry Andric
29000b57cec5SDimitry Andric // Shift and accumulate into the register. If a 16-bit chunk is zero, then
29010b57cec5SDimitry Andric // skip it and defer the shift to the next chunk.
29020b57cec5SDimitry Andric unsigned ShiftCarriedForwards = 16;
29030b57cec5SDimitry Andric for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
29040b57cec5SDimitry Andric uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
29050b57cec5SDimitry Andric
29060b57cec5SDimitry Andric if (ImmChunk != 0) {
29070b57cec5SDimitry Andric TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
29080b57cec5SDimitry Andric TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, STI);
29090b57cec5SDimitry Andric ShiftCarriedForwards = 0;
29100b57cec5SDimitry Andric }
29110b57cec5SDimitry Andric
29120b57cec5SDimitry Andric ShiftCarriedForwards += 16;
29130b57cec5SDimitry Andric }
29140b57cec5SDimitry Andric ShiftCarriedForwards -= 16;
29150b57cec5SDimitry Andric
29160b57cec5SDimitry Andric // Finish any remaining shifts left by trailing zeros.
29170b57cec5SDimitry Andric if (ShiftCarriedForwards)
29180b57cec5SDimitry Andric TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
29190b57cec5SDimitry Andric
29200b57cec5SDimitry Andric if (UseSrcReg)
29210b57cec5SDimitry Andric TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
29220b57cec5SDimitry Andric
29230b57cec5SDimitry Andric return false;
29240b57cec5SDimitry Andric }
29250b57cec5SDimitry Andric
expandLoadImm(MCInst & Inst,bool Is32BitImm,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)29260b57cec5SDimitry Andric bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
29270b57cec5SDimitry Andric MCStreamer &Out, const MCSubtargetInfo *STI) {
29280b57cec5SDimitry Andric const MCOperand &ImmOp = Inst.getOperand(1);
29290b57cec5SDimitry Andric assert(ImmOp.isImm() && "expected immediate operand kind");
29300b57cec5SDimitry Andric const MCOperand &DstRegOp = Inst.getOperand(0);
29310b57cec5SDimitry Andric assert(DstRegOp.isReg() && "expected register operand kind");
29320b57cec5SDimitry Andric
29330b57cec5SDimitry Andric if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
29340b57cec5SDimitry Andric Is32BitImm, false, IDLoc, Out, STI))
29350b57cec5SDimitry Andric return true;
29360b57cec5SDimitry Andric
29370b57cec5SDimitry Andric return false;
29380b57cec5SDimitry Andric }
29390b57cec5SDimitry Andric
expandLoadAddress(unsigned DstReg,unsigned BaseReg,const MCOperand & Offset,bool Is32BitAddress,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)29400b57cec5SDimitry Andric bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
29410b57cec5SDimitry Andric const MCOperand &Offset,
29420b57cec5SDimitry Andric bool Is32BitAddress, SMLoc IDLoc,
29430b57cec5SDimitry Andric MCStreamer &Out,
29440b57cec5SDimitry Andric const MCSubtargetInfo *STI) {
29450b57cec5SDimitry Andric // la can't produce a usable address when addresses are 64-bit.
29460b57cec5SDimitry Andric if (Is32BitAddress && ABI.ArePtrs64bit()) {
2947480093f4SDimitry Andric Warning(IDLoc, "la used to load 64-bit address");
29480b57cec5SDimitry Andric // Continue as if we had 'dla' instead.
29490b57cec5SDimitry Andric Is32BitAddress = false;
29500b57cec5SDimitry Andric }
29510b57cec5SDimitry Andric
29520b57cec5SDimitry Andric // dla requires 64-bit addresses.
29530b57cec5SDimitry Andric if (!Is32BitAddress && !hasMips3()) {
29540b57cec5SDimitry Andric Error(IDLoc, "instruction requires a 64-bit architecture");
29550b57cec5SDimitry Andric return true;
29560b57cec5SDimitry Andric }
29570b57cec5SDimitry Andric
29580b57cec5SDimitry Andric if (!Offset.isImm())
29590b57cec5SDimitry Andric return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
29600b57cec5SDimitry Andric Is32BitAddress, IDLoc, Out, STI);
29610b57cec5SDimitry Andric
29620b57cec5SDimitry Andric if (!ABI.ArePtrs64bit()) {
29630b57cec5SDimitry Andric // Continue as if we had 'la' whether we had 'la' or 'dla'.
29640b57cec5SDimitry Andric Is32BitAddress = true;
29650b57cec5SDimitry Andric }
29660b57cec5SDimitry Andric
29670b57cec5SDimitry Andric return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
29680b57cec5SDimitry Andric IDLoc, Out, STI);
29690b57cec5SDimitry Andric }
29700b57cec5SDimitry Andric
loadAndAddSymbolAddress(const MCExpr * SymExpr,unsigned DstReg,unsigned SrcReg,bool Is32BitSym,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)29710b57cec5SDimitry Andric bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
29720b57cec5SDimitry Andric unsigned DstReg, unsigned SrcReg,
29730b57cec5SDimitry Andric bool Is32BitSym, SMLoc IDLoc,
29740b57cec5SDimitry Andric MCStreamer &Out,
29750b57cec5SDimitry Andric const MCSubtargetInfo *STI) {
29760b57cec5SDimitry Andric MipsTargetStreamer &TOut = getTargetStreamer();
29778bcb0991SDimitry Andric bool UseSrcReg = SrcReg != Mips::NoRegister && SrcReg != Mips::ZERO &&
29788bcb0991SDimitry Andric SrcReg != Mips::ZERO_64;
29790b57cec5SDimitry Andric warnIfNoMacro(IDLoc);
29800b57cec5SDimitry Andric
29818bcb0991SDimitry Andric if (inPicMode()) {
29820b57cec5SDimitry Andric MCValue Res;
29830b57cec5SDimitry Andric if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
29840b57cec5SDimitry Andric Error(IDLoc, "expected relocatable expression");
29850b57cec5SDimitry Andric return true;
29860b57cec5SDimitry Andric }
29870b57cec5SDimitry Andric if (Res.getSymB() != nullptr) {
29880b57cec5SDimitry Andric Error(IDLoc, "expected relocatable expression with only one symbol");
29890b57cec5SDimitry Andric return true;
29900b57cec5SDimitry Andric }
29910b57cec5SDimitry Andric
29928bcb0991SDimitry Andric bool IsPtr64 = ABI.ArePtrs64bit();
29938bcb0991SDimitry Andric bool IsLocalSym =
29948bcb0991SDimitry Andric Res.getSymA()->getSymbol().isInSection() ||
29950b57cec5SDimitry Andric Res.getSymA()->getSymbol().isTemporary() ||
29960b57cec5SDimitry Andric (Res.getSymA()->getSymbol().isELF() &&
29970b57cec5SDimitry Andric cast<MCSymbolELF>(Res.getSymA()->getSymbol()).getBinding() ==
29988bcb0991SDimitry Andric ELF::STB_LOCAL);
299974626c16SDimitry Andric // For O32, "$"-prefixed symbols are recognized as temporary while
300074626c16SDimitry Andric // .L-prefixed symbols are not (PrivateGlobalPrefix is "$"). Recognize ".L"
300174626c16SDimitry Andric // manually.
300274626c16SDimitry Andric if (ABI.IsO32() && Res.getSymA()->getSymbol().getName().starts_with(".L"))
300374626c16SDimitry Andric IsLocalSym = true;
300406c3fb27SDimitry Andric bool UseXGOT = STI->hasFeature(Mips::FeatureXGOT) && !IsLocalSym;
30058bcb0991SDimitry Andric
30068bcb0991SDimitry Andric // The case where the result register is $25 is somewhat special. If the
30078bcb0991SDimitry Andric // symbol in the final relocation is external and not modified with a
30088bcb0991SDimitry Andric // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT16
30098bcb0991SDimitry Andric // or R_MIPS_CALL16 instead of R_MIPS_GOT_DISP in 64-bit case.
30108bcb0991SDimitry Andric if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
30118bcb0991SDimitry Andric Res.getConstant() == 0 && !IsLocalSym) {
30128bcb0991SDimitry Andric if (UseXGOT) {
30138bcb0991SDimitry Andric const MCExpr *CallHiExpr = MipsMCExpr::create(MipsMCExpr::MEK_CALL_HI16,
30148bcb0991SDimitry Andric SymExpr, getContext());
30158bcb0991SDimitry Andric const MCExpr *CallLoExpr = MipsMCExpr::create(MipsMCExpr::MEK_CALL_LO16,
30168bcb0991SDimitry Andric SymExpr, getContext());
30178bcb0991SDimitry Andric TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(CallHiExpr), IDLoc,
30188bcb0991SDimitry Andric STI);
30198bcb0991SDimitry Andric TOut.emitRRR(IsPtr64 ? Mips::DADDu : Mips::ADDu, DstReg, DstReg, GPReg,
30208bcb0991SDimitry Andric IDLoc, STI);
30218bcb0991SDimitry Andric TOut.emitRRX(IsPtr64 ? Mips::LD : Mips::LW, DstReg, DstReg,
30228bcb0991SDimitry Andric MCOperand::createExpr(CallLoExpr), IDLoc, STI);
30238bcb0991SDimitry Andric } else {
30240b57cec5SDimitry Andric const MCExpr *CallExpr =
30250b57cec5SDimitry Andric MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
30268bcb0991SDimitry Andric TOut.emitRRX(IsPtr64 ? Mips::LD : Mips::LW, DstReg, GPReg,
30278bcb0991SDimitry Andric MCOperand::createExpr(CallExpr), IDLoc, STI);
30280b57cec5SDimitry Andric }
30298bcb0991SDimitry Andric return false;
30300b57cec5SDimitry Andric }
30310b57cec5SDimitry Andric
30320b57cec5SDimitry Andric unsigned TmpReg = DstReg;
30330b57cec5SDimitry Andric if (UseSrcReg &&
30340b57cec5SDimitry Andric getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
30350b57cec5SDimitry Andric SrcReg)) {
30360b57cec5SDimitry Andric // If $rs is the same as $rd, we need to use AT.
30370b57cec5SDimitry Andric // If it is not available we exit.
30380b57cec5SDimitry Andric unsigned ATReg = getATReg(IDLoc);
30390b57cec5SDimitry Andric if (!ATReg)
30400b57cec5SDimitry Andric return true;
30410b57cec5SDimitry Andric TmpReg = ATReg;
30420b57cec5SDimitry Andric }
30430b57cec5SDimitry Andric
3044480093f4SDimitry Andric // FIXME: In case of N32 / N64 ABI and emabled XGOT, local addresses
3045480093f4SDimitry Andric // loaded using R_MIPS_GOT_PAGE / R_MIPS_GOT_OFST pair of relocations.
3046480093f4SDimitry Andric // FIXME: Implement XGOT for microMIPS.
30478bcb0991SDimitry Andric if (UseXGOT) {
30488bcb0991SDimitry Andric // Loading address from XGOT
30498bcb0991SDimitry Andric // External GOT: lui $tmp, %got_hi(symbol)($gp)
30508bcb0991SDimitry Andric // addu $tmp, $tmp, $gp
30518bcb0991SDimitry Andric // lw $tmp, %got_lo(symbol)($tmp)
30528bcb0991SDimitry Andric // >addiu $tmp, $tmp, offset
30538bcb0991SDimitry Andric // >addiu $rd, $tmp, $rs
30548bcb0991SDimitry Andric // The addiu's marked with a '>' may be omitted if they are redundant. If
30558bcb0991SDimitry Andric // this happens then the last instruction must use $rd as the result
30568bcb0991SDimitry Andric // register.
30578bcb0991SDimitry Andric const MCExpr *CallHiExpr =
30588bcb0991SDimitry Andric MipsMCExpr::create(MipsMCExpr::MEK_GOT_HI16, SymExpr, getContext());
30598bcb0991SDimitry Andric const MCExpr *CallLoExpr = MipsMCExpr::create(
30608bcb0991SDimitry Andric MipsMCExpr::MEK_GOT_LO16, Res.getSymA(), getContext());
30610b57cec5SDimitry Andric
30628bcb0991SDimitry Andric TOut.emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(CallHiExpr), IDLoc,
30638bcb0991SDimitry Andric STI);
30648bcb0991SDimitry Andric TOut.emitRRR(IsPtr64 ? Mips::DADDu : Mips::ADDu, TmpReg, TmpReg, GPReg,
30658bcb0991SDimitry Andric IDLoc, STI);
30668bcb0991SDimitry Andric TOut.emitRRX(IsPtr64 ? Mips::LD : Mips::LW, TmpReg, TmpReg,
30678bcb0991SDimitry Andric MCOperand::createExpr(CallLoExpr), IDLoc, STI);
30688bcb0991SDimitry Andric
30698bcb0991SDimitry Andric if (Res.getConstant() != 0)
30708bcb0991SDimitry Andric TOut.emitRRX(IsPtr64 ? Mips::DADDiu : Mips::ADDiu, TmpReg, TmpReg,
30718bcb0991SDimitry Andric MCOperand::createExpr(MCConstantExpr::create(
30728bcb0991SDimitry Andric Res.getConstant(), getContext())),
30730b57cec5SDimitry Andric IDLoc, STI);
30740b57cec5SDimitry Andric
30750b57cec5SDimitry Andric if (UseSrcReg)
30768bcb0991SDimitry Andric TOut.emitRRR(IsPtr64 ? Mips::DADDu : Mips::ADDu, DstReg, TmpReg, SrcReg,
30770b57cec5SDimitry Andric IDLoc, STI);
30780b57cec5SDimitry Andric return false;
30790b57cec5SDimitry Andric }
30800b57cec5SDimitry Andric
30818bcb0991SDimitry Andric const MipsMCExpr *GotExpr = nullptr;
30828bcb0991SDimitry Andric const MCExpr *LoExpr = nullptr;
3083480093f4SDimitry Andric if (ABI.IsN32() || ABI.IsN64()) {
30840b57cec5SDimitry Andric // The remaining cases are:
30850b57cec5SDimitry Andric // Small offset: ld $tmp, %got_disp(symbol)($gp)
30860b57cec5SDimitry Andric // >daddiu $tmp, $tmp, offset
30870b57cec5SDimitry Andric // >daddu $rd, $tmp, $rs
30880b57cec5SDimitry Andric // The daddiu's marked with a '>' may be omitted if they are redundant. If
30890b57cec5SDimitry Andric // this happens then the last instruction must use $rd as the result
30900b57cec5SDimitry Andric // register.
30918bcb0991SDimitry Andric GotExpr = MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, Res.getSymA(),
30920b57cec5SDimitry Andric getContext());
30930b57cec5SDimitry Andric if (Res.getConstant() != 0) {
30940b57cec5SDimitry Andric // Symbols fully resolve with just the %got_disp(symbol) but we
30950b57cec5SDimitry Andric // must still account for any offset to the symbol for
30960b57cec5SDimitry Andric // expressions like symbol+8.
30970b57cec5SDimitry Andric LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
30980b57cec5SDimitry Andric
30990b57cec5SDimitry Andric // FIXME: Offsets greater than 16 bits are not yet implemented.
31000b57cec5SDimitry Andric // FIXME: The correct range is a 32-bit sign-extended number.
31010b57cec5SDimitry Andric if (Res.getConstant() < -0x8000 || Res.getConstant() > 0x7fff) {
31020b57cec5SDimitry Andric Error(IDLoc, "macro instruction uses large offset, which is not "
31030b57cec5SDimitry Andric "currently supported");
31040b57cec5SDimitry Andric return true;
31050b57cec5SDimitry Andric }
31060b57cec5SDimitry Andric }
31078bcb0991SDimitry Andric } else {
31088bcb0991SDimitry Andric // The remaining cases are:
31098bcb0991SDimitry Andric // External GOT: lw $tmp, %got(symbol)($gp)
31108bcb0991SDimitry Andric // >addiu $tmp, $tmp, offset
31118bcb0991SDimitry Andric // >addiu $rd, $tmp, $rs
31128bcb0991SDimitry Andric // Local GOT: lw $tmp, %got(symbol+offset)($gp)
31138bcb0991SDimitry Andric // addiu $tmp, $tmp, %lo(symbol+offset)($gp)
31148bcb0991SDimitry Andric // >addiu $rd, $tmp, $rs
31158bcb0991SDimitry Andric // The addiu's marked with a '>' may be omitted if they are redundant. If
31168bcb0991SDimitry Andric // this happens then the last instruction must use $rd as the result
31178bcb0991SDimitry Andric // register.
31188bcb0991SDimitry Andric if (IsLocalSym) {
31198bcb0991SDimitry Andric GotExpr =
31208bcb0991SDimitry Andric MipsMCExpr::create(MipsMCExpr::MEK_GOT, SymExpr, getContext());
31218bcb0991SDimitry Andric LoExpr = MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
31228bcb0991SDimitry Andric } else {
31238bcb0991SDimitry Andric // External symbols fully resolve the symbol with just the %got(symbol)
31248bcb0991SDimitry Andric // but we must still account for any offset to the symbol for
31258bcb0991SDimitry Andric // expressions like symbol+8.
31268bcb0991SDimitry Andric GotExpr = MipsMCExpr::create(MipsMCExpr::MEK_GOT, Res.getSymA(),
31278bcb0991SDimitry Andric getContext());
31288bcb0991SDimitry Andric if (Res.getConstant() != 0)
31298bcb0991SDimitry Andric LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
31308bcb0991SDimitry Andric }
31310b57cec5SDimitry Andric }
31320b57cec5SDimitry Andric
31338bcb0991SDimitry Andric TOut.emitRRX(IsPtr64 ? Mips::LD : Mips::LW, TmpReg, GPReg,
31348bcb0991SDimitry Andric MCOperand::createExpr(GotExpr), IDLoc, STI);
31350b57cec5SDimitry Andric
31360b57cec5SDimitry Andric if (LoExpr)
31378bcb0991SDimitry Andric TOut.emitRRX(IsPtr64 ? Mips::DADDiu : Mips::ADDiu, TmpReg, TmpReg,
31388bcb0991SDimitry Andric MCOperand::createExpr(LoExpr), IDLoc, STI);
31390b57cec5SDimitry Andric
31400b57cec5SDimitry Andric if (UseSrcReg)
31418bcb0991SDimitry Andric TOut.emitRRR(IsPtr64 ? Mips::DADDu : Mips::ADDu, DstReg, TmpReg, SrcReg,
31428bcb0991SDimitry Andric IDLoc, STI);
31430b57cec5SDimitry Andric
31440b57cec5SDimitry Andric return false;
31450b57cec5SDimitry Andric }
31460b57cec5SDimitry Andric
31470b57cec5SDimitry Andric const MipsMCExpr *HiExpr =
31480b57cec5SDimitry Andric MipsMCExpr::create(MipsMCExpr::MEK_HI, SymExpr, getContext());
31490b57cec5SDimitry Andric const MipsMCExpr *LoExpr =
31500b57cec5SDimitry Andric MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
31510b57cec5SDimitry Andric
31520b57cec5SDimitry Andric // This is the 64-bit symbol address expansion.
31530b57cec5SDimitry Andric if (ABI.ArePtrs64bit() && isGP64bit()) {
31540b57cec5SDimitry Andric // We need AT for the 64-bit expansion in the cases where the optional
31550b57cec5SDimitry Andric // source register is the destination register and for the superscalar
31560b57cec5SDimitry Andric // scheduled form.
31570b57cec5SDimitry Andric //
31580b57cec5SDimitry Andric // If it is not available we exit if the destination is the same as the
31590b57cec5SDimitry Andric // source register.
31600b57cec5SDimitry Andric
31610b57cec5SDimitry Andric const MipsMCExpr *HighestExpr =
31620b57cec5SDimitry Andric MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, SymExpr, getContext());
31630b57cec5SDimitry Andric const MipsMCExpr *HigherExpr =
31640b57cec5SDimitry Andric MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, SymExpr, getContext());
31650b57cec5SDimitry Andric
31660b57cec5SDimitry Andric bool RdRegIsRsReg =
316706c3fb27SDimitry Andric UseSrcReg &&
31680b57cec5SDimitry Andric getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg);
31690b57cec5SDimitry Andric
31700b57cec5SDimitry Andric if (canUseATReg() && UseSrcReg && RdRegIsRsReg) {
31710b57cec5SDimitry Andric unsigned ATReg = getATReg(IDLoc);
31720b57cec5SDimitry Andric
31730b57cec5SDimitry Andric // If $rs is the same as $rd:
31740b57cec5SDimitry Andric // (d)la $rd, sym($rd) => lui $at, %highest(sym)
31750b57cec5SDimitry Andric // daddiu $at, $at, %higher(sym)
31760b57cec5SDimitry Andric // dsll $at, $at, 16
31770b57cec5SDimitry Andric // daddiu $at, $at, %hi(sym)
31780b57cec5SDimitry Andric // dsll $at, $at, 16
31790b57cec5SDimitry Andric // daddiu $at, $at, %lo(sym)
31800b57cec5SDimitry Andric // daddu $rd, $at, $rd
31810b57cec5SDimitry Andric TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
31820b57cec5SDimitry Andric STI);
31830b57cec5SDimitry Andric TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
31840b57cec5SDimitry Andric MCOperand::createExpr(HigherExpr), IDLoc, STI);
31850b57cec5SDimitry Andric TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
31860b57cec5SDimitry Andric TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
31870b57cec5SDimitry Andric IDLoc, STI);
31880b57cec5SDimitry Andric TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
31890b57cec5SDimitry Andric TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
31900b57cec5SDimitry Andric IDLoc, STI);
31910b57cec5SDimitry Andric TOut.emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, STI);
31920b57cec5SDimitry Andric
31930b57cec5SDimitry Andric return false;
31940b57cec5SDimitry Andric } else if (canUseATReg() && !RdRegIsRsReg && DstReg != getATReg(IDLoc)) {
31950b57cec5SDimitry Andric unsigned ATReg = getATReg(IDLoc);
31960b57cec5SDimitry Andric
31970b57cec5SDimitry Andric // If the $rs is different from $rd or if $rs isn't specified and we
31980b57cec5SDimitry Andric // have $at available:
31990b57cec5SDimitry Andric // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
32000b57cec5SDimitry Andric // lui $at, %hi(sym)
32010b57cec5SDimitry Andric // daddiu $rd, $rd, %higher(sym)
32020b57cec5SDimitry Andric // daddiu $at, $at, %lo(sym)
32030b57cec5SDimitry Andric // dsll32 $rd, $rd, 0
32040b57cec5SDimitry Andric // daddu $rd, $rd, $at
32050b57cec5SDimitry Andric // (daddu $rd, $rd, $rs)
32060b57cec5SDimitry Andric //
32070b57cec5SDimitry Andric // Which is preferred for superscalar issue.
32080b57cec5SDimitry Andric TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
32090b57cec5SDimitry Andric STI);
32100b57cec5SDimitry Andric TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
32110b57cec5SDimitry Andric TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
32120b57cec5SDimitry Andric MCOperand::createExpr(HigherExpr), IDLoc, STI);
32130b57cec5SDimitry Andric TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
32140b57cec5SDimitry Andric IDLoc, STI);
32150b57cec5SDimitry Andric TOut.emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, STI);
32160b57cec5SDimitry Andric TOut.emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, STI);
32170b57cec5SDimitry Andric if (UseSrcReg)
32180b57cec5SDimitry Andric TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
32190b57cec5SDimitry Andric
32200b57cec5SDimitry Andric return false;
32210b57cec5SDimitry Andric } else if ((!canUseATReg() && !RdRegIsRsReg) ||
32220b57cec5SDimitry Andric (canUseATReg() && DstReg == getATReg(IDLoc))) {
32230b57cec5SDimitry Andric // Otherwise, synthesize the address in the destination register
32240b57cec5SDimitry Andric // serially:
32250b57cec5SDimitry Andric // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
32260b57cec5SDimitry Andric // daddiu $rd, $rd, %higher(sym)
32270b57cec5SDimitry Andric // dsll $rd, $rd, 16
32280b57cec5SDimitry Andric // daddiu $rd, $rd, %hi(sym)
32290b57cec5SDimitry Andric // dsll $rd, $rd, 16
32300b57cec5SDimitry Andric // daddiu $rd, $rd, %lo(sym)
32310b57cec5SDimitry Andric TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
32320b57cec5SDimitry Andric STI);
32330b57cec5SDimitry Andric TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
32340b57cec5SDimitry Andric MCOperand::createExpr(HigherExpr), IDLoc, STI);
32350b57cec5SDimitry Andric TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI);
32360b57cec5SDimitry Andric TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
32370b57cec5SDimitry Andric MCOperand::createExpr(HiExpr), IDLoc, STI);
32380b57cec5SDimitry Andric TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI);
32390b57cec5SDimitry Andric TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
32400b57cec5SDimitry Andric MCOperand::createExpr(LoExpr), IDLoc, STI);
32410b57cec5SDimitry Andric if (UseSrcReg)
32420b57cec5SDimitry Andric TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
32430b57cec5SDimitry Andric
32440b57cec5SDimitry Andric return false;
32450b57cec5SDimitry Andric } else {
32460b57cec5SDimitry Andric // We have a case where SrcReg == DstReg and we don't have $at
32470b57cec5SDimitry Andric // available. We can't expand this case, so error out appropriately.
32480b57cec5SDimitry Andric assert(SrcReg == DstReg && !canUseATReg() &&
32490b57cec5SDimitry Andric "Could have expanded dla but didn't?");
32500b57cec5SDimitry Andric reportParseError(IDLoc,
32510b57cec5SDimitry Andric "pseudo-instruction requires $at, which is not available");
32520b57cec5SDimitry Andric return true;
32530b57cec5SDimitry Andric }
32540b57cec5SDimitry Andric }
32550b57cec5SDimitry Andric
32560b57cec5SDimitry Andric // And now, the 32-bit symbol address expansion:
32570b57cec5SDimitry Andric // If $rs is the same as $rd:
32580b57cec5SDimitry Andric // (d)la $rd, sym($rd) => lui $at, %hi(sym)
32590b57cec5SDimitry Andric // ori $at, $at, %lo(sym)
32600b57cec5SDimitry Andric // addu $rd, $at, $rd
32610b57cec5SDimitry Andric // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
32620b57cec5SDimitry Andric // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
32630b57cec5SDimitry Andric // ori $rd, $rd, %lo(sym)
32640b57cec5SDimitry Andric // (addu $rd, $rd, $rs)
32650b57cec5SDimitry Andric unsigned TmpReg = DstReg;
32660b57cec5SDimitry Andric if (UseSrcReg &&
32670b57cec5SDimitry Andric getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
32680b57cec5SDimitry Andric // If $rs is the same as $rd, we need to use AT.
32690b57cec5SDimitry Andric // If it is not available we exit.
32700b57cec5SDimitry Andric unsigned ATReg = getATReg(IDLoc);
32710b57cec5SDimitry Andric if (!ATReg)
32720b57cec5SDimitry Andric return true;
32730b57cec5SDimitry Andric TmpReg = ATReg;
32740b57cec5SDimitry Andric }
32750b57cec5SDimitry Andric
32760b57cec5SDimitry Andric TOut.emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
32770b57cec5SDimitry Andric TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
32780b57cec5SDimitry Andric IDLoc, STI);
32790b57cec5SDimitry Andric
32800b57cec5SDimitry Andric if (UseSrcReg)
32810b57cec5SDimitry Andric TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
32820b57cec5SDimitry Andric else
32830b57cec5SDimitry Andric assert(
32840b57cec5SDimitry Andric getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, TmpReg));
32850b57cec5SDimitry Andric
32860b57cec5SDimitry Andric return false;
32870b57cec5SDimitry Andric }
32880b57cec5SDimitry Andric
32890b57cec5SDimitry Andric // Each double-precision register DO-D15 overlaps with two of the single
32900b57cec5SDimitry Andric // precision registers F0-F31. As an example, all of the following hold true:
32910b57cec5SDimitry Andric // D0 + 1 == F1, F1 + 1 == D1, F1 + 1 == F2, depending on the context.
nextReg(unsigned Reg)32920b57cec5SDimitry Andric static unsigned nextReg(unsigned Reg) {
32930b57cec5SDimitry Andric if (MipsMCRegisterClasses[Mips::FGR32RegClassID].contains(Reg))
32940b57cec5SDimitry Andric return Reg == (unsigned)Mips::F31 ? (unsigned)Mips::F0 : Reg + 1;
32950b57cec5SDimitry Andric switch (Reg) {
32960b57cec5SDimitry Andric default: llvm_unreachable("Unknown register in assembly macro expansion!");
32970b57cec5SDimitry Andric case Mips::ZERO: return Mips::AT;
32980b57cec5SDimitry Andric case Mips::AT: return Mips::V0;
32990b57cec5SDimitry Andric case Mips::V0: return Mips::V1;
33000b57cec5SDimitry Andric case Mips::V1: return Mips::A0;
33010b57cec5SDimitry Andric case Mips::A0: return Mips::A1;
33020b57cec5SDimitry Andric case Mips::A1: return Mips::A2;
33030b57cec5SDimitry Andric case Mips::A2: return Mips::A3;
33040b57cec5SDimitry Andric case Mips::A3: return Mips::T0;
33050b57cec5SDimitry Andric case Mips::T0: return Mips::T1;
33060b57cec5SDimitry Andric case Mips::T1: return Mips::T2;
33070b57cec5SDimitry Andric case Mips::T2: return Mips::T3;
33080b57cec5SDimitry Andric case Mips::T3: return Mips::T4;
33090b57cec5SDimitry Andric case Mips::T4: return Mips::T5;
33100b57cec5SDimitry Andric case Mips::T5: return Mips::T6;
33110b57cec5SDimitry Andric case Mips::T6: return Mips::T7;
33120b57cec5SDimitry Andric case Mips::T7: return Mips::S0;
33130b57cec5SDimitry Andric case Mips::S0: return Mips::S1;
33140b57cec5SDimitry Andric case Mips::S1: return Mips::S2;
33150b57cec5SDimitry Andric case Mips::S2: return Mips::S3;
33160b57cec5SDimitry Andric case Mips::S3: return Mips::S4;
33170b57cec5SDimitry Andric case Mips::S4: return Mips::S5;
33180b57cec5SDimitry Andric case Mips::S5: return Mips::S6;
33190b57cec5SDimitry Andric case Mips::S6: return Mips::S7;
33200b57cec5SDimitry Andric case Mips::S7: return Mips::T8;
33210b57cec5SDimitry Andric case Mips::T8: return Mips::T9;
33220b57cec5SDimitry Andric case Mips::T9: return Mips::K0;
33230b57cec5SDimitry Andric case Mips::K0: return Mips::K1;
33240b57cec5SDimitry Andric case Mips::K1: return Mips::GP;
33250b57cec5SDimitry Andric case Mips::GP: return Mips::SP;
33260b57cec5SDimitry Andric case Mips::SP: return Mips::FP;
33270b57cec5SDimitry Andric case Mips::FP: return Mips::RA;
33280b57cec5SDimitry Andric case Mips::RA: return Mips::ZERO;
33290b57cec5SDimitry Andric case Mips::D0: return Mips::F1;
33300b57cec5SDimitry Andric case Mips::D1: return Mips::F3;
33310b57cec5SDimitry Andric case Mips::D2: return Mips::F5;
33320b57cec5SDimitry Andric case Mips::D3: return Mips::F7;
33330b57cec5SDimitry Andric case Mips::D4: return Mips::F9;
33340b57cec5SDimitry Andric case Mips::D5: return Mips::F11;
33350b57cec5SDimitry Andric case Mips::D6: return Mips::F13;
33360b57cec5SDimitry Andric case Mips::D7: return Mips::F15;
33370b57cec5SDimitry Andric case Mips::D8: return Mips::F17;
33380b57cec5SDimitry Andric case Mips::D9: return Mips::F19;
33390b57cec5SDimitry Andric case Mips::D10: return Mips::F21;
33400b57cec5SDimitry Andric case Mips::D11: return Mips::F23;
33410b57cec5SDimitry Andric case Mips::D12: return Mips::F25;
33420b57cec5SDimitry Andric case Mips::D13: return Mips::F27;
33430b57cec5SDimitry Andric case Mips::D14: return Mips::F29;
33440b57cec5SDimitry Andric case Mips::D15: return Mips::F31;
33450b57cec5SDimitry Andric }
33460b57cec5SDimitry Andric }
33470b57cec5SDimitry Andric
33480b57cec5SDimitry Andric // FIXME: This method is too general. In principle we should compute the number
33490b57cec5SDimitry Andric // of instructions required to synthesize the immediate inline compared to
33500b57cec5SDimitry Andric // synthesizing the address inline and relying on non .text sections.
33510b57cec5SDimitry Andric // For static O32 and N32 this may yield a small benefit, for static N64 this is
33520b57cec5SDimitry Andric // likely to yield a much larger benefit as we have to synthesize a 64bit
33530b57cec5SDimitry Andric // address to load a 64 bit value.
emitPartialAddress(MipsTargetStreamer & TOut,SMLoc IDLoc,MCSymbol * Sym)33540b57cec5SDimitry Andric bool MipsAsmParser::emitPartialAddress(MipsTargetStreamer &TOut, SMLoc IDLoc,
33550b57cec5SDimitry Andric MCSymbol *Sym) {
33560b57cec5SDimitry Andric unsigned ATReg = getATReg(IDLoc);
33570b57cec5SDimitry Andric if (!ATReg)
33580b57cec5SDimitry Andric return true;
33590b57cec5SDimitry Andric
33600b57cec5SDimitry Andric if(IsPicEnabled) {
33610b57cec5SDimitry Andric const MCExpr *GotSym =
33620b57cec5SDimitry Andric MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
33630b57cec5SDimitry Andric const MipsMCExpr *GotExpr =
33640b57cec5SDimitry Andric MipsMCExpr::create(MipsMCExpr::MEK_GOT, GotSym, getContext());
33650b57cec5SDimitry Andric
33660b57cec5SDimitry Andric if(isABI_O32() || isABI_N32()) {
33670b57cec5SDimitry Andric TOut.emitRRX(Mips::LW, ATReg, GPReg, MCOperand::createExpr(GotExpr),
33680b57cec5SDimitry Andric IDLoc, STI);
33690b57cec5SDimitry Andric } else { //isABI_N64()
33700b57cec5SDimitry Andric TOut.emitRRX(Mips::LD, ATReg, GPReg, MCOperand::createExpr(GotExpr),
33710b57cec5SDimitry Andric IDLoc, STI);
33720b57cec5SDimitry Andric }
33730b57cec5SDimitry Andric } else { //!IsPicEnabled
33740b57cec5SDimitry Andric const MCExpr *HiSym =
33750b57cec5SDimitry Andric MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
33760b57cec5SDimitry Andric const MipsMCExpr *HiExpr =
33770b57cec5SDimitry Andric MipsMCExpr::create(MipsMCExpr::MEK_HI, HiSym, getContext());
33780b57cec5SDimitry Andric
33790b57cec5SDimitry Andric // FIXME: This is technically correct but gives a different result to gas,
33800b57cec5SDimitry Andric // but gas is incomplete there (it has a fixme noting it doesn't work with
33810b57cec5SDimitry Andric // 64-bit addresses).
33820b57cec5SDimitry Andric // FIXME: With -msym32 option, the address expansion for N64 should probably
33830b57cec5SDimitry Andric // use the O32 / N32 case. It's safe to use the 64 address expansion as the
33840b57cec5SDimitry Andric // symbol's value is considered sign extended.
33850b57cec5SDimitry Andric if(isABI_O32() || isABI_N32()) {
33860b57cec5SDimitry Andric TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
33870b57cec5SDimitry Andric } else { //isABI_N64()
33880b57cec5SDimitry Andric const MCExpr *HighestSym =
33890b57cec5SDimitry Andric MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
33900b57cec5SDimitry Andric const MipsMCExpr *HighestExpr =
33910b57cec5SDimitry Andric MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, HighestSym, getContext());
33920b57cec5SDimitry Andric const MCExpr *HigherSym =
33930b57cec5SDimitry Andric MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
33940b57cec5SDimitry Andric const MipsMCExpr *HigherExpr =
33950b57cec5SDimitry Andric MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, HigherSym, getContext());
33960b57cec5SDimitry Andric
33970b57cec5SDimitry Andric TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
33980b57cec5SDimitry Andric STI);
33990b57cec5SDimitry Andric TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
34000b57cec5SDimitry Andric MCOperand::createExpr(HigherExpr), IDLoc, STI);
34010b57cec5SDimitry Andric TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
34020b57cec5SDimitry Andric TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
34030b57cec5SDimitry Andric IDLoc, STI);
34040b57cec5SDimitry Andric TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
34050b57cec5SDimitry Andric }
34060b57cec5SDimitry Andric }
34070b57cec5SDimitry Andric return false;
34080b57cec5SDimitry Andric }
34090b57cec5SDimitry Andric
convertIntToDoubleImm(uint64_t ImmOp64)3410c14a5a88SDimitry Andric static uint64_t convertIntToDoubleImm(uint64_t ImmOp64) {
3411c14a5a88SDimitry Andric // If ImmOp64 is AsmToken::Integer type (all bits set to zero in the
3412c14a5a88SDimitry Andric // exponent field), convert it to double (e.g. 1 to 1.0)
3413c14a5a88SDimitry Andric if ((Hi_32(ImmOp64) & 0x7ff00000) == 0) {
3414c14a5a88SDimitry Andric APFloat RealVal(APFloat::IEEEdouble(), ImmOp64);
3415c14a5a88SDimitry Andric ImmOp64 = RealVal.bitcastToAPInt().getZExtValue();
3416c14a5a88SDimitry Andric }
3417c14a5a88SDimitry Andric return ImmOp64;
3418c14a5a88SDimitry Andric }
3419c14a5a88SDimitry Andric
covertDoubleImmToSingleImm(uint64_t ImmOp64)3420c14a5a88SDimitry Andric static uint32_t covertDoubleImmToSingleImm(uint64_t ImmOp64) {
3421c14a5a88SDimitry Andric // Conversion of a double in an uint64_t to a float in a uint32_t,
3422c14a5a88SDimitry Andric // retaining the bit pattern of a float.
342306c3fb27SDimitry Andric double DoubleImm = llvm::bit_cast<double>(ImmOp64);
3424c14a5a88SDimitry Andric float TmpFloat = static_cast<float>(DoubleImm);
342506c3fb27SDimitry Andric return llvm::bit_cast<uint32_t>(TmpFloat);
3426c14a5a88SDimitry Andric }
3427c14a5a88SDimitry Andric
expandLoadSingleImmToGPR(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)3428c14a5a88SDimitry Andric bool MipsAsmParser::expandLoadSingleImmToGPR(MCInst &Inst, SMLoc IDLoc,
3429c14a5a88SDimitry Andric MCStreamer &Out,
3430c14a5a88SDimitry Andric const MCSubtargetInfo *STI) {
3431c14a5a88SDimitry Andric assert(Inst.getNumOperands() == 2 && "Invalid operand count");
3432c14a5a88SDimitry Andric assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isImm() &&
3433c14a5a88SDimitry Andric "Invalid instruction operand.");
3434c14a5a88SDimitry Andric
3435c14a5a88SDimitry Andric unsigned FirstReg = Inst.getOperand(0).getReg();
3436c14a5a88SDimitry Andric uint64_t ImmOp64 = Inst.getOperand(1).getImm();
3437c14a5a88SDimitry Andric
34388bcb0991SDimitry Andric uint32_t ImmOp32 = covertDoubleImmToSingleImm(convertIntToDoubleImm(ImmOp64));
3439c14a5a88SDimitry Andric
34408bcb0991SDimitry Andric return loadImmediate(ImmOp32, FirstReg, Mips::NoRegister, true, false, IDLoc,
3441c14a5a88SDimitry Andric Out, STI);
3442c14a5a88SDimitry Andric }
3443c14a5a88SDimitry Andric
expandLoadSingleImmToFPR(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)3444c14a5a88SDimitry Andric bool MipsAsmParser::expandLoadSingleImmToFPR(MCInst &Inst, SMLoc IDLoc,
34450b57cec5SDimitry Andric MCStreamer &Out,
34460b57cec5SDimitry Andric const MCSubtargetInfo *STI) {
34470b57cec5SDimitry Andric MipsTargetStreamer &TOut = getTargetStreamer();
34480b57cec5SDimitry Andric assert(Inst.getNumOperands() == 2 && "Invalid operand count");
34490b57cec5SDimitry Andric assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isImm() &&
34500b57cec5SDimitry Andric "Invalid instruction operand.");
34510b57cec5SDimitry Andric
34520b57cec5SDimitry Andric unsigned FirstReg = Inst.getOperand(0).getReg();
34530b57cec5SDimitry Andric uint64_t ImmOp64 = Inst.getOperand(1).getImm();
34540b57cec5SDimitry Andric
3455c14a5a88SDimitry Andric ImmOp64 = convertIntToDoubleImm(ImmOp64);
34560b57cec5SDimitry Andric
3457c14a5a88SDimitry Andric uint32_t ImmOp32 = covertDoubleImmToSingleImm(ImmOp64);
34580b57cec5SDimitry Andric
34598bcb0991SDimitry Andric unsigned TmpReg = Mips::ZERO;
34608bcb0991SDimitry Andric if (ImmOp32 != 0) {
34618bcb0991SDimitry Andric TmpReg = getATReg(IDLoc);
3462c14a5a88SDimitry Andric if (!TmpReg)
3463c14a5a88SDimitry Andric return true;
34648bcb0991SDimitry Andric }
34650b57cec5SDimitry Andric
3466c14a5a88SDimitry Andric if (Lo_32(ImmOp64) == 0) {
34678bcb0991SDimitry Andric if (TmpReg != Mips::ZERO && loadImmediate(ImmOp32, TmpReg, Mips::NoRegister,
34688bcb0991SDimitry Andric true, false, IDLoc, Out, STI))
34690b57cec5SDimitry Andric return true;
3470c14a5a88SDimitry Andric TOut.emitRR(Mips::MTC1, FirstReg, TmpReg, IDLoc, STI);
34710b57cec5SDimitry Andric return false;
34720b57cec5SDimitry Andric }
34730b57cec5SDimitry Andric
34740b57cec5SDimitry Andric MCSection *CS = getStreamer().getCurrentSectionOnly();
34750b57cec5SDimitry Andric // FIXME: Enhance this expansion to use the .lit4 & .lit8 sections
34760b57cec5SDimitry Andric // where appropriate.
3477c14a5a88SDimitry Andric MCSection *ReadOnlySection =
3478c14a5a88SDimitry Andric getContext().getELFSection(".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
34790b57cec5SDimitry Andric
34800b57cec5SDimitry Andric MCSymbol *Sym = getContext().createTempSymbol();
34810b57cec5SDimitry Andric const MCExpr *LoSym =
34820b57cec5SDimitry Andric MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
34830b57cec5SDimitry Andric const MipsMCExpr *LoExpr =
34840b57cec5SDimitry Andric MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
34850b57cec5SDimitry Andric
348681ad6265SDimitry Andric getStreamer().switchSection(ReadOnlySection);
34875ffd83dbSDimitry Andric getStreamer().emitLabel(Sym, IDLoc);
34885ffd83dbSDimitry Andric getStreamer().emitInt32(ImmOp32);
348981ad6265SDimitry Andric getStreamer().switchSection(CS);
34900b57cec5SDimitry Andric
34910b57cec5SDimitry Andric if (emitPartialAddress(TOut, IDLoc, Sym))
34920b57cec5SDimitry Andric return true;
3493c14a5a88SDimitry Andric TOut.emitRRX(Mips::LWC1, FirstReg, TmpReg, MCOperand::createExpr(LoExpr),
3494c14a5a88SDimitry Andric IDLoc, STI);
34950b57cec5SDimitry Andric return false;
34960b57cec5SDimitry Andric }
34970b57cec5SDimitry Andric
expandLoadDoubleImmToGPR(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)3498c14a5a88SDimitry Andric bool MipsAsmParser::expandLoadDoubleImmToGPR(MCInst &Inst, SMLoc IDLoc,
3499c14a5a88SDimitry Andric MCStreamer &Out,
3500c14a5a88SDimitry Andric const MCSubtargetInfo *STI) {
3501c14a5a88SDimitry Andric MipsTargetStreamer &TOut = getTargetStreamer();
3502c14a5a88SDimitry Andric assert(Inst.getNumOperands() == 2 && "Invalid operand count");
3503c14a5a88SDimitry Andric assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isImm() &&
3504c14a5a88SDimitry Andric "Invalid instruction operand.");
3505c14a5a88SDimitry Andric
3506c14a5a88SDimitry Andric unsigned FirstReg = Inst.getOperand(0).getReg();
3507c14a5a88SDimitry Andric uint64_t ImmOp64 = Inst.getOperand(1).getImm();
3508c14a5a88SDimitry Andric
3509c14a5a88SDimitry Andric ImmOp64 = convertIntToDoubleImm(ImmOp64);
3510c14a5a88SDimitry Andric
35118bcb0991SDimitry Andric if (Lo_32(ImmOp64) == 0) {
35128bcb0991SDimitry Andric if (isGP64bit()) {
35138bcb0991SDimitry Andric if (loadImmediate(ImmOp64, FirstReg, Mips::NoRegister, false, false,
35148bcb0991SDimitry Andric IDLoc, Out, STI))
35150b57cec5SDimitry Andric return true;
35160b57cec5SDimitry Andric } else {
35178bcb0991SDimitry Andric if (loadImmediate(Hi_32(ImmOp64), FirstReg, Mips::NoRegister, true, false,
35180b57cec5SDimitry Andric IDLoc, Out, STI))
35190b57cec5SDimitry Andric return true;
35200b57cec5SDimitry Andric
35218bcb0991SDimitry Andric if (loadImmediate(0, nextReg(FirstReg), Mips::NoRegister, true, false,
35220b57cec5SDimitry Andric IDLoc, Out, STI))
35230b57cec5SDimitry Andric return true;
35240b57cec5SDimitry Andric }
3525c14a5a88SDimitry Andric return false;
35260b57cec5SDimitry Andric }
35270b57cec5SDimitry Andric
35280b57cec5SDimitry Andric MCSection *CS = getStreamer().getCurrentSectionOnly();
3529c14a5a88SDimitry Andric MCSection *ReadOnlySection =
3530c14a5a88SDimitry Andric getContext().getELFSection(".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
35310b57cec5SDimitry Andric
35320b57cec5SDimitry Andric MCSymbol *Sym = getContext().createTempSymbol();
35330b57cec5SDimitry Andric const MCExpr *LoSym =
35340b57cec5SDimitry Andric MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
35350b57cec5SDimitry Andric const MipsMCExpr *LoExpr =
35360b57cec5SDimitry Andric MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
35370b57cec5SDimitry Andric
353881ad6265SDimitry Andric getStreamer().switchSection(ReadOnlySection);
35395ffd83dbSDimitry Andric getStreamer().emitLabel(Sym, IDLoc);
3540bdd1243dSDimitry Andric getStreamer().emitValueToAlignment(Align(8));
35415ffd83dbSDimitry Andric getStreamer().emitIntValue(ImmOp64, 8);
354281ad6265SDimitry Andric getStreamer().switchSection(CS);
35430b57cec5SDimitry Andric
35448bcb0991SDimitry Andric unsigned TmpReg = getATReg(IDLoc);
35458bcb0991SDimitry Andric if (!TmpReg)
35468bcb0991SDimitry Andric return true;
35478bcb0991SDimitry Andric
35480b57cec5SDimitry Andric if (emitPartialAddress(TOut, IDLoc, Sym))
35490b57cec5SDimitry Andric return true;
3550c14a5a88SDimitry Andric
35518bcb0991SDimitry Andric TOut.emitRRX(isABI_N64() ? Mips::DADDiu : Mips::ADDiu, TmpReg, TmpReg,
35528bcb0991SDimitry Andric MCOperand::createExpr(LoExpr), IDLoc, STI);
35530b57cec5SDimitry Andric
35548bcb0991SDimitry Andric if (isGP64bit())
3555c14a5a88SDimitry Andric TOut.emitRRI(Mips::LD, FirstReg, TmpReg, 0, IDLoc, STI);
35560b57cec5SDimitry Andric else {
3557c14a5a88SDimitry Andric TOut.emitRRI(Mips::LW, FirstReg, TmpReg, 0, IDLoc, STI);
3558c14a5a88SDimitry Andric TOut.emitRRI(Mips::LW, nextReg(FirstReg), TmpReg, 4, IDLoc, STI);
35590b57cec5SDimitry Andric }
35600b57cec5SDimitry Andric return false;
3561c14a5a88SDimitry Andric }
3562c14a5a88SDimitry Andric
expandLoadDoubleImmToFPR(MCInst & Inst,bool Is64FPU,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)3563c14a5a88SDimitry Andric bool MipsAsmParser::expandLoadDoubleImmToFPR(MCInst &Inst, bool Is64FPU,
3564c14a5a88SDimitry Andric SMLoc IDLoc, MCStreamer &Out,
3565c14a5a88SDimitry Andric const MCSubtargetInfo *STI) {
3566c14a5a88SDimitry Andric MipsTargetStreamer &TOut = getTargetStreamer();
3567c14a5a88SDimitry Andric assert(Inst.getNumOperands() == 2 && "Invalid operand count");
3568c14a5a88SDimitry Andric assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isImm() &&
3569c14a5a88SDimitry Andric "Invalid instruction operand.");
3570c14a5a88SDimitry Andric
3571c14a5a88SDimitry Andric unsigned FirstReg = Inst.getOperand(0).getReg();
3572c14a5a88SDimitry Andric uint64_t ImmOp64 = Inst.getOperand(1).getImm();
3573c14a5a88SDimitry Andric
3574c14a5a88SDimitry Andric ImmOp64 = convertIntToDoubleImm(ImmOp64);
3575c14a5a88SDimitry Andric
35768bcb0991SDimitry Andric unsigned TmpReg = Mips::ZERO;
35778bcb0991SDimitry Andric if (ImmOp64 != 0) {
35788bcb0991SDimitry Andric TmpReg = getATReg(IDLoc);
3579c14a5a88SDimitry Andric if (!TmpReg)
3580c14a5a88SDimitry Andric return true;
35818bcb0991SDimitry Andric }
3582c14a5a88SDimitry Andric
35838bcb0991SDimitry Andric if ((Lo_32(ImmOp64) == 0) &&
35848bcb0991SDimitry Andric !((Hi_32(ImmOp64) & 0xffff0000) && (Hi_32(ImmOp64) & 0x0000ffff))) {
35858bcb0991SDimitry Andric if (isGP64bit()) {
35868bcb0991SDimitry Andric if (TmpReg != Mips::ZERO &&
35878bcb0991SDimitry Andric loadImmediate(ImmOp64, TmpReg, Mips::NoRegister, false, false, IDLoc,
35880b57cec5SDimitry Andric Out, STI))
35890b57cec5SDimitry Andric return true;
3590c14a5a88SDimitry Andric TOut.emitRR(Mips::DMTC1, FirstReg, TmpReg, IDLoc, STI);
3591c14a5a88SDimitry Andric return false;
3592c14a5a88SDimitry Andric }
3593c14a5a88SDimitry Andric
35948bcb0991SDimitry Andric if (TmpReg != Mips::ZERO &&
35958bcb0991SDimitry Andric loadImmediate(Hi_32(ImmOp64), TmpReg, Mips::NoRegister, true, false,
35968bcb0991SDimitry Andric IDLoc, Out, STI))
3597c14a5a88SDimitry Andric return true;
3598c14a5a88SDimitry Andric
3599c14a5a88SDimitry Andric if (hasMips32r2()) {
36000b57cec5SDimitry Andric TOut.emitRR(Mips::MTC1, FirstReg, Mips::ZERO, IDLoc, STI);
3601c14a5a88SDimitry Andric TOut.emitRRR(Mips::MTHC1_D32, FirstReg, FirstReg, TmpReg, IDLoc, STI);
36020b57cec5SDimitry Andric } else {
3603c14a5a88SDimitry Andric TOut.emitRR(Mips::MTC1, nextReg(FirstReg), TmpReg, IDLoc, STI);
36040b57cec5SDimitry Andric TOut.emitRR(Mips::MTC1, FirstReg, Mips::ZERO, IDLoc, STI);
36050b57cec5SDimitry Andric }
36060b57cec5SDimitry Andric return false;
36070b57cec5SDimitry Andric }
36080b57cec5SDimitry Andric
36090b57cec5SDimitry Andric MCSection *CS = getStreamer().getCurrentSectionOnly();
36100b57cec5SDimitry Andric // FIXME: Enhance this expansion to use the .lit4 & .lit8 sections
36110b57cec5SDimitry Andric // where appropriate.
3612c14a5a88SDimitry Andric MCSection *ReadOnlySection =
3613c14a5a88SDimitry Andric getContext().getELFSection(".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
36140b57cec5SDimitry Andric
36150b57cec5SDimitry Andric MCSymbol *Sym = getContext().createTempSymbol();
36160b57cec5SDimitry Andric const MCExpr *LoSym =
36170b57cec5SDimitry Andric MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
36180b57cec5SDimitry Andric const MipsMCExpr *LoExpr =
36190b57cec5SDimitry Andric MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
36200b57cec5SDimitry Andric
362181ad6265SDimitry Andric getStreamer().switchSection(ReadOnlySection);
36225ffd83dbSDimitry Andric getStreamer().emitLabel(Sym, IDLoc);
3623bdd1243dSDimitry Andric getStreamer().emitValueToAlignment(Align(8));
36245ffd83dbSDimitry Andric getStreamer().emitIntValue(ImmOp64, 8);
362581ad6265SDimitry Andric getStreamer().switchSection(CS);
36260b57cec5SDimitry Andric
36270b57cec5SDimitry Andric if (emitPartialAddress(TOut, IDLoc, Sym))
36280b57cec5SDimitry Andric return true;
3629c14a5a88SDimitry Andric
3630c14a5a88SDimitry Andric TOut.emitRRX(Is64FPU ? Mips::LDC164 : Mips::LDC1, FirstReg, TmpReg,
36310b57cec5SDimitry Andric MCOperand::createExpr(LoExpr), IDLoc, STI);
3632c14a5a88SDimitry Andric
36330b57cec5SDimitry Andric return false;
36340b57cec5SDimitry Andric }
36350b57cec5SDimitry Andric
expandUncondBranchMMPseudo(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)36360b57cec5SDimitry Andric bool MipsAsmParser::expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
36370b57cec5SDimitry Andric MCStreamer &Out,
36380b57cec5SDimitry Andric const MCSubtargetInfo *STI) {
36390b57cec5SDimitry Andric MipsTargetStreamer &TOut = getTargetStreamer();
36400b57cec5SDimitry Andric
3641bdd1243dSDimitry Andric assert(MII.get(Inst.getOpcode()).getNumOperands() == 1 &&
36420b57cec5SDimitry Andric "unexpected number of operands");
36430b57cec5SDimitry Andric
36440b57cec5SDimitry Andric MCOperand Offset = Inst.getOperand(0);
36450b57cec5SDimitry Andric if (Offset.isExpr()) {
36460b57cec5SDimitry Andric Inst.clear();
36470b57cec5SDimitry Andric Inst.setOpcode(Mips::BEQ_MM);
36480b57cec5SDimitry Andric Inst.addOperand(MCOperand::createReg(Mips::ZERO));
36490b57cec5SDimitry Andric Inst.addOperand(MCOperand::createReg(Mips::ZERO));
36500b57cec5SDimitry Andric Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
36510b57cec5SDimitry Andric } else {
36520b57cec5SDimitry Andric assert(Offset.isImm() && "expected immediate operand kind");
36530b57cec5SDimitry Andric if (isInt<11>(Offset.getImm())) {
36540b57cec5SDimitry Andric // If offset fits into 11 bits then this instruction becomes microMIPS
36550b57cec5SDimitry Andric // 16-bit unconditional branch instruction.
36560b57cec5SDimitry Andric if (inMicroMipsMode())
36570b57cec5SDimitry Andric Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
36580b57cec5SDimitry Andric } else {
36590b57cec5SDimitry Andric if (!isInt<17>(Offset.getImm()))
36600b57cec5SDimitry Andric return Error(IDLoc, "branch target out of range");
36618bcb0991SDimitry Andric if (offsetToAlignment(Offset.getImm(), Align(2)))
36620b57cec5SDimitry Andric return Error(IDLoc, "branch to misaligned address");
36630b57cec5SDimitry Andric Inst.clear();
36640b57cec5SDimitry Andric Inst.setOpcode(Mips::BEQ_MM);
36650b57cec5SDimitry Andric Inst.addOperand(MCOperand::createReg(Mips::ZERO));
36660b57cec5SDimitry Andric Inst.addOperand(MCOperand::createReg(Mips::ZERO));
36670b57cec5SDimitry Andric Inst.addOperand(MCOperand::createImm(Offset.getImm()));
36680b57cec5SDimitry Andric }
36690b57cec5SDimitry Andric }
36705ffd83dbSDimitry Andric Out.emitInstruction(Inst, *STI);
36710b57cec5SDimitry Andric
36720b57cec5SDimitry Andric // If .set reorder is active and branch instruction has a delay slot,
36730b57cec5SDimitry Andric // emit a NOP after it.
3674bdd1243dSDimitry Andric const MCInstrDesc &MCID = MII.get(Inst.getOpcode());
36750b57cec5SDimitry Andric if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
36760b57cec5SDimitry Andric TOut.emitEmptyDelaySlot(true, IDLoc, STI);
36770b57cec5SDimitry Andric
36780b57cec5SDimitry Andric return false;
36790b57cec5SDimitry Andric }
36800b57cec5SDimitry Andric
expandBranchImm(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)36810b57cec5SDimitry Andric bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
36820b57cec5SDimitry Andric const MCSubtargetInfo *STI) {
36830b57cec5SDimitry Andric MipsTargetStreamer &TOut = getTargetStreamer();
36840b57cec5SDimitry Andric const MCOperand &DstRegOp = Inst.getOperand(0);
36850b57cec5SDimitry Andric assert(DstRegOp.isReg() && "expected register operand kind");
36860b57cec5SDimitry Andric
36870b57cec5SDimitry Andric const MCOperand &ImmOp = Inst.getOperand(1);
36880b57cec5SDimitry Andric assert(ImmOp.isImm() && "expected immediate operand kind");
36890b57cec5SDimitry Andric
36900b57cec5SDimitry Andric const MCOperand &MemOffsetOp = Inst.getOperand(2);
36910b57cec5SDimitry Andric assert((MemOffsetOp.isImm() || MemOffsetOp.isExpr()) &&
36920b57cec5SDimitry Andric "expected immediate or expression operand");
36930b57cec5SDimitry Andric
36940b57cec5SDimitry Andric bool IsLikely = false;
36950b57cec5SDimitry Andric
36960b57cec5SDimitry Andric unsigned OpCode = 0;
36970b57cec5SDimitry Andric switch(Inst.getOpcode()) {
36980b57cec5SDimitry Andric case Mips::BneImm:
36990b57cec5SDimitry Andric OpCode = Mips::BNE;
37000b57cec5SDimitry Andric break;
37010b57cec5SDimitry Andric case Mips::BeqImm:
37020b57cec5SDimitry Andric OpCode = Mips::BEQ;
37030b57cec5SDimitry Andric break;
37040b57cec5SDimitry Andric case Mips::BEQLImmMacro:
37050b57cec5SDimitry Andric OpCode = Mips::BEQL;
37060b57cec5SDimitry Andric IsLikely = true;
37070b57cec5SDimitry Andric break;
37080b57cec5SDimitry Andric case Mips::BNELImmMacro:
37090b57cec5SDimitry Andric OpCode = Mips::BNEL;
37100b57cec5SDimitry Andric IsLikely = true;
37110b57cec5SDimitry Andric break;
37120b57cec5SDimitry Andric default:
37130b57cec5SDimitry Andric llvm_unreachable("Unknown immediate branch pseudo-instruction.");
37140b57cec5SDimitry Andric break;
37150b57cec5SDimitry Andric }
37160b57cec5SDimitry Andric
37170b57cec5SDimitry Andric int64_t ImmValue = ImmOp.getImm();
37180b57cec5SDimitry Andric if (ImmValue == 0) {
37190b57cec5SDimitry Andric if (IsLikely) {
37200b57cec5SDimitry Andric TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO,
37210b57cec5SDimitry Andric MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI);
37220b57cec5SDimitry Andric TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
37230b57cec5SDimitry Andric } else
37240b57cec5SDimitry Andric TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
37250b57cec5SDimitry Andric STI);
37260b57cec5SDimitry Andric } else {
37270b57cec5SDimitry Andric warnIfNoMacro(IDLoc);
37280b57cec5SDimitry Andric
37290b57cec5SDimitry Andric unsigned ATReg = getATReg(IDLoc);
37300b57cec5SDimitry Andric if (!ATReg)
37310b57cec5SDimitry Andric return true;
37320b57cec5SDimitry Andric
37330b57cec5SDimitry Andric if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
37340b57cec5SDimitry Andric IDLoc, Out, STI))
37350b57cec5SDimitry Andric return true;
37360b57cec5SDimitry Andric
37370b57cec5SDimitry Andric if (IsLikely) {
37380b57cec5SDimitry Andric TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg,
37390b57cec5SDimitry Andric MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI);
37400b57cec5SDimitry Andric TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
37410b57cec5SDimitry Andric } else
37420b57cec5SDimitry Andric TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, STI);
37430b57cec5SDimitry Andric }
37440b57cec5SDimitry Andric return false;
37450b57cec5SDimitry Andric }
37460b57cec5SDimitry Andric
expandMem16Inst(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI,bool IsLoad)3747480093f4SDimitry Andric void MipsAsmParser::expandMem16Inst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
37480b57cec5SDimitry Andric const MCSubtargetInfo *STI, bool IsLoad) {
3749480093f4SDimitry Andric unsigned NumOp = Inst.getNumOperands();
3750480093f4SDimitry Andric assert((NumOp == 3 || NumOp == 4) && "unexpected operands number");
3751480093f4SDimitry Andric unsigned StartOp = NumOp == 3 ? 0 : 1;
3752480093f4SDimitry Andric
3753480093f4SDimitry Andric const MCOperand &DstRegOp = Inst.getOperand(StartOp);
37540b57cec5SDimitry Andric assert(DstRegOp.isReg() && "expected register operand kind");
3755480093f4SDimitry Andric const MCOperand &BaseRegOp = Inst.getOperand(StartOp + 1);
37560b57cec5SDimitry Andric assert(BaseRegOp.isReg() && "expected register operand kind");
3757480093f4SDimitry Andric const MCOperand &OffsetOp = Inst.getOperand(StartOp + 2);
37580b57cec5SDimitry Andric
37590b57cec5SDimitry Andric MipsTargetStreamer &TOut = getTargetStreamer();
3760480093f4SDimitry Andric unsigned OpCode = Inst.getOpcode();
37610b57cec5SDimitry Andric unsigned DstReg = DstRegOp.getReg();
37620b57cec5SDimitry Andric unsigned BaseReg = BaseRegOp.getReg();
37630b57cec5SDimitry Andric unsigned TmpReg = DstReg;
37640b57cec5SDimitry Andric
3765bdd1243dSDimitry Andric const MCInstrDesc &Desc = MII.get(OpCode);
3766bdd1243dSDimitry Andric int16_t DstRegClass = Desc.operands()[StartOp].RegClass;
37670b57cec5SDimitry Andric unsigned DstRegClassID =
37680b57cec5SDimitry Andric getContext().getRegisterInfo()->getRegClass(DstRegClass).getID();
37690b57cec5SDimitry Andric bool IsGPR = (DstRegClassID == Mips::GPR32RegClassID) ||
37700b57cec5SDimitry Andric (DstRegClassID == Mips::GPR64RegClassID);
37710b57cec5SDimitry Andric
37720b57cec5SDimitry Andric if (!IsLoad || !IsGPR || (BaseReg == DstReg)) {
37730b57cec5SDimitry Andric // At this point we need AT to perform the expansions
37740b57cec5SDimitry Andric // and we exit if it is not available.
37750b57cec5SDimitry Andric TmpReg = getATReg(IDLoc);
37760b57cec5SDimitry Andric if (!TmpReg)
37770b57cec5SDimitry Andric return;
37780b57cec5SDimitry Andric }
37790b57cec5SDimitry Andric
3780480093f4SDimitry Andric auto emitInstWithOffset = [&](const MCOperand &Off) {
3781480093f4SDimitry Andric if (NumOp == 3)
3782480093f4SDimitry Andric TOut.emitRRX(OpCode, DstReg, TmpReg, Off, IDLoc, STI);
3783480093f4SDimitry Andric else
3784480093f4SDimitry Andric TOut.emitRRRX(OpCode, DstReg, DstReg, TmpReg, Off, IDLoc, STI);
3785480093f4SDimitry Andric };
37868bcb0991SDimitry Andric
37870b57cec5SDimitry Andric if (OffsetOp.isImm()) {
37880b57cec5SDimitry Andric int64_t LoOffset = OffsetOp.getImm() & 0xffff;
37890b57cec5SDimitry Andric int64_t HiOffset = OffsetOp.getImm() & ~0xffff;
37900b57cec5SDimitry Andric
37910b57cec5SDimitry Andric // If msb of LoOffset is 1(negative number) we must increment
37920b57cec5SDimitry Andric // HiOffset to account for the sign-extension of the low part.
37930b57cec5SDimitry Andric if (LoOffset & 0x8000)
37940b57cec5SDimitry Andric HiOffset += 0x10000;
37950b57cec5SDimitry Andric
37960b57cec5SDimitry Andric bool IsLargeOffset = HiOffset != 0;
37970b57cec5SDimitry Andric
37980b57cec5SDimitry Andric if (IsLargeOffset) {
3799480093f4SDimitry Andric bool Is32BitImm = isInt<32>(OffsetOp.getImm());
38000b57cec5SDimitry Andric if (loadImmediate(HiOffset, TmpReg, Mips::NoRegister, Is32BitImm, true,
38010b57cec5SDimitry Andric IDLoc, Out, STI))
38020b57cec5SDimitry Andric return;
38030b57cec5SDimitry Andric }
38040b57cec5SDimitry Andric
38050b57cec5SDimitry Andric if (BaseReg != Mips::ZERO && BaseReg != Mips::ZERO_64)
3806480093f4SDimitry Andric TOut.emitRRR(ABI.ArePtrs64bit() ? Mips::DADDu : Mips::ADDu, TmpReg,
3807480093f4SDimitry Andric TmpReg, BaseReg, IDLoc, STI);
3808480093f4SDimitry Andric emitInstWithOffset(MCOperand::createImm(int16_t(LoOffset)));
38090b57cec5SDimitry Andric return;
38100b57cec5SDimitry Andric }
38110b57cec5SDimitry Andric
38128bcb0991SDimitry Andric if (OffsetOp.isExpr()) {
38130b57cec5SDimitry Andric if (inPicMode()) {
38140b57cec5SDimitry Andric // FIXME:
38150b57cec5SDimitry Andric // c) Check that immediates of R_MIPS_GOT16/R_MIPS_LO16 relocations
38160b57cec5SDimitry Andric // do not exceed 16-bit.
38170b57cec5SDimitry Andric // d) Use R_MIPS_GOT_PAGE/R_MIPS_GOT_OFST relocations instead
38180b57cec5SDimitry Andric // of R_MIPS_GOT_DISP in appropriate cases to reduce number
38190b57cec5SDimitry Andric // of GOT entries.
38208bcb0991SDimitry Andric MCValue Res;
38218bcb0991SDimitry Andric if (!OffsetOp.getExpr()->evaluateAsRelocatable(Res, nullptr, nullptr)) {
38228bcb0991SDimitry Andric Error(IDLoc, "expected relocatable expression");
38238bcb0991SDimitry Andric return;
38248bcb0991SDimitry Andric }
38258bcb0991SDimitry Andric if (Res.getSymB() != nullptr) {
38268bcb0991SDimitry Andric Error(IDLoc, "expected relocatable expression with only one symbol");
38278bcb0991SDimitry Andric return;
38288bcb0991SDimitry Andric }
38298bcb0991SDimitry Andric
38308bcb0991SDimitry Andric loadAndAddSymbolAddress(Res.getSymA(), TmpReg, BaseReg,
38318bcb0991SDimitry Andric !ABI.ArePtrs64bit(), IDLoc, Out, STI);
3832480093f4SDimitry Andric emitInstWithOffset(MCOperand::createImm(int16_t(Res.getConstant())));
38330b57cec5SDimitry Andric } else {
38348bcb0991SDimitry Andric // FIXME: Implement 64-bit case.
38358bcb0991SDimitry Andric // 1) lw $8, sym => lui $8, %hi(sym)
38368bcb0991SDimitry Andric // lw $8, %lo(sym)($8)
38378bcb0991SDimitry Andric // 2) sw $8, sym => lui $at, %hi(sym)
38388bcb0991SDimitry Andric // sw $8, %lo(sym)($at)
3839480093f4SDimitry Andric const MCExpr *OffExpr = OffsetOp.getExpr();
38400b57cec5SDimitry Andric MCOperand LoOperand = MCOperand::createExpr(
3841480093f4SDimitry Andric MipsMCExpr::create(MipsMCExpr::MEK_LO, OffExpr, getContext()));
38420b57cec5SDimitry Andric MCOperand HiOperand = MCOperand::createExpr(
3843480093f4SDimitry Andric MipsMCExpr::create(MipsMCExpr::MEK_HI, OffExpr, getContext()));
38440b57cec5SDimitry Andric
3845480093f4SDimitry Andric if (ABI.IsN64()) {
3846480093f4SDimitry Andric MCOperand HighestOperand = MCOperand::createExpr(
3847480093f4SDimitry Andric MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, OffExpr, getContext()));
3848480093f4SDimitry Andric MCOperand HigherOperand = MCOperand::createExpr(
3849480093f4SDimitry Andric MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, OffExpr, getContext()));
3850480093f4SDimitry Andric
3851480093f4SDimitry Andric TOut.emitRX(Mips::LUi, TmpReg, HighestOperand, IDLoc, STI);
3852480093f4SDimitry Andric TOut.emitRRX(Mips::DADDiu, TmpReg, TmpReg, HigherOperand, IDLoc, STI);
3853480093f4SDimitry Andric TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI);
3854480093f4SDimitry Andric TOut.emitRRX(Mips::DADDiu, TmpReg, TmpReg, HiOperand, IDLoc, STI);
3855480093f4SDimitry Andric TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI);
3856480093f4SDimitry Andric if (BaseReg != Mips::ZERO && BaseReg != Mips::ZERO_64)
3857480093f4SDimitry Andric TOut.emitRRR(Mips::DADDu, TmpReg, TmpReg, BaseReg, IDLoc, STI);
3858480093f4SDimitry Andric emitInstWithOffset(LoOperand);
3859480093f4SDimitry Andric } else {
38608bcb0991SDimitry Andric // Generate the base address in TmpReg.
38618bcb0991SDimitry Andric TOut.emitRX(Mips::LUi, TmpReg, HiOperand, IDLoc, STI);
38628bcb0991SDimitry Andric if (BaseReg != Mips::ZERO)
38638bcb0991SDimitry Andric TOut.emitRRR(Mips::ADDu, TmpReg, TmpReg, BaseReg, IDLoc, STI);
38648bcb0991SDimitry Andric // Emit the load or store with the adjusted base and offset.
3865480093f4SDimitry Andric emitInstWithOffset(LoOperand);
38660b57cec5SDimitry Andric }
3867480093f4SDimitry Andric }
3868480093f4SDimitry Andric return;
3869480093f4SDimitry Andric }
3870480093f4SDimitry Andric
3871480093f4SDimitry Andric llvm_unreachable("unexpected operand type");
3872480093f4SDimitry Andric }
3873480093f4SDimitry Andric
expandMem9Inst(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI,bool IsLoad)3874480093f4SDimitry Andric void MipsAsmParser::expandMem9Inst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3875480093f4SDimitry Andric const MCSubtargetInfo *STI, bool IsLoad) {
3876480093f4SDimitry Andric unsigned NumOp = Inst.getNumOperands();
3877480093f4SDimitry Andric assert((NumOp == 3 || NumOp == 4) && "unexpected operands number");
3878480093f4SDimitry Andric unsigned StartOp = NumOp == 3 ? 0 : 1;
3879480093f4SDimitry Andric
3880480093f4SDimitry Andric const MCOperand &DstRegOp = Inst.getOperand(StartOp);
3881480093f4SDimitry Andric assert(DstRegOp.isReg() && "expected register operand kind");
3882480093f4SDimitry Andric const MCOperand &BaseRegOp = Inst.getOperand(StartOp + 1);
3883480093f4SDimitry Andric assert(BaseRegOp.isReg() && "expected register operand kind");
3884480093f4SDimitry Andric const MCOperand &OffsetOp = Inst.getOperand(StartOp + 2);
3885480093f4SDimitry Andric
3886480093f4SDimitry Andric MipsTargetStreamer &TOut = getTargetStreamer();
3887480093f4SDimitry Andric unsigned OpCode = Inst.getOpcode();
3888480093f4SDimitry Andric unsigned DstReg = DstRegOp.getReg();
3889480093f4SDimitry Andric unsigned BaseReg = BaseRegOp.getReg();
3890480093f4SDimitry Andric unsigned TmpReg = DstReg;
3891480093f4SDimitry Andric
3892bdd1243dSDimitry Andric const MCInstrDesc &Desc = MII.get(OpCode);
3893bdd1243dSDimitry Andric int16_t DstRegClass = Desc.operands()[StartOp].RegClass;
3894480093f4SDimitry Andric unsigned DstRegClassID =
3895480093f4SDimitry Andric getContext().getRegisterInfo()->getRegClass(DstRegClass).getID();
3896480093f4SDimitry Andric bool IsGPR = (DstRegClassID == Mips::GPR32RegClassID) ||
3897480093f4SDimitry Andric (DstRegClassID == Mips::GPR64RegClassID);
3898480093f4SDimitry Andric
3899480093f4SDimitry Andric if (!IsLoad || !IsGPR || (BaseReg == DstReg)) {
3900480093f4SDimitry Andric // At this point we need AT to perform the expansions
3901480093f4SDimitry Andric // and we exit if it is not available.
3902480093f4SDimitry Andric TmpReg = getATReg(IDLoc);
3903480093f4SDimitry Andric if (!TmpReg)
3904480093f4SDimitry Andric return;
3905480093f4SDimitry Andric }
3906480093f4SDimitry Andric
3907480093f4SDimitry Andric auto emitInst = [&]() {
3908480093f4SDimitry Andric if (NumOp == 3)
3909480093f4SDimitry Andric TOut.emitRRX(OpCode, DstReg, TmpReg, MCOperand::createImm(0), IDLoc, STI);
3910480093f4SDimitry Andric else
3911480093f4SDimitry Andric TOut.emitRRRX(OpCode, DstReg, DstReg, TmpReg, MCOperand::createImm(0),
3912480093f4SDimitry Andric IDLoc, STI);
3913480093f4SDimitry Andric };
3914480093f4SDimitry Andric
3915480093f4SDimitry Andric if (OffsetOp.isImm()) {
3916480093f4SDimitry Andric loadImmediate(OffsetOp.getImm(), TmpReg, BaseReg, !ABI.ArePtrs64bit(), true,
3917480093f4SDimitry Andric IDLoc, Out, STI);
3918480093f4SDimitry Andric emitInst();
3919480093f4SDimitry Andric return;
3920480093f4SDimitry Andric }
3921480093f4SDimitry Andric
3922480093f4SDimitry Andric if (OffsetOp.isExpr()) {
3923480093f4SDimitry Andric loadAndAddSymbolAddress(OffsetOp.getExpr(), TmpReg, BaseReg,
3924480093f4SDimitry Andric !ABI.ArePtrs64bit(), IDLoc, Out, STI);
3925480093f4SDimitry Andric emitInst();
39268bcb0991SDimitry Andric return;
39278bcb0991SDimitry Andric }
39288bcb0991SDimitry Andric
39298bcb0991SDimitry Andric llvm_unreachable("unexpected operand type");
39300b57cec5SDimitry Andric }
39310b57cec5SDimitry Andric
expandLoadStoreMultiple(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)39320b57cec5SDimitry Andric bool MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
39330b57cec5SDimitry Andric MCStreamer &Out,
39340b57cec5SDimitry Andric const MCSubtargetInfo *STI) {
39350b57cec5SDimitry Andric unsigned OpNum = Inst.getNumOperands();
39360b57cec5SDimitry Andric unsigned Opcode = Inst.getOpcode();
39370b57cec5SDimitry Andric unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
39380b57cec5SDimitry Andric
39390b57cec5SDimitry Andric assert(Inst.getOperand(OpNum - 1).isImm() &&
39400b57cec5SDimitry Andric Inst.getOperand(OpNum - 2).isReg() &&
39410b57cec5SDimitry Andric Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
39420b57cec5SDimitry Andric
39430b57cec5SDimitry Andric if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
39440b57cec5SDimitry Andric Inst.getOperand(OpNum - 1).getImm() >= 0 &&
39450b57cec5SDimitry Andric (Inst.getOperand(OpNum - 2).getReg() == Mips::SP ||
39460b57cec5SDimitry Andric Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) &&
39470b57cec5SDimitry Andric (Inst.getOperand(OpNum - 3).getReg() == Mips::RA ||
39480b57cec5SDimitry Andric Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) {
39490b57cec5SDimitry Andric // It can be implemented as SWM16 or LWM16 instruction.
39500b57cec5SDimitry Andric if (inMicroMipsMode() && hasMips32r6())
39510b57cec5SDimitry Andric NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6;
39520b57cec5SDimitry Andric else
39530b57cec5SDimitry Andric NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
39540b57cec5SDimitry Andric }
39550b57cec5SDimitry Andric
39560b57cec5SDimitry Andric Inst.setOpcode(NewOpcode);
39575ffd83dbSDimitry Andric Out.emitInstruction(Inst, *STI);
39580b57cec5SDimitry Andric return false;
39590b57cec5SDimitry Andric }
39600b57cec5SDimitry Andric
expandCondBranches(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)39610b57cec5SDimitry Andric bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
39620b57cec5SDimitry Andric MCStreamer &Out,
39630b57cec5SDimitry Andric const MCSubtargetInfo *STI) {
39640b57cec5SDimitry Andric MipsTargetStreamer &TOut = getTargetStreamer();
39650b57cec5SDimitry Andric bool EmittedNoMacroWarning = false;
39660b57cec5SDimitry Andric unsigned PseudoOpcode = Inst.getOpcode();
39670b57cec5SDimitry Andric unsigned SrcReg = Inst.getOperand(0).getReg();
39680b57cec5SDimitry Andric const MCOperand &TrgOp = Inst.getOperand(1);
39690b57cec5SDimitry Andric const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
39700b57cec5SDimitry Andric
39710b57cec5SDimitry Andric unsigned ZeroSrcOpcode, ZeroTrgOpcode;
39720b57cec5SDimitry Andric bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
39730b57cec5SDimitry Andric
39740b57cec5SDimitry Andric unsigned TrgReg;
39750b57cec5SDimitry Andric if (TrgOp.isReg())
39760b57cec5SDimitry Andric TrgReg = TrgOp.getReg();
39770b57cec5SDimitry Andric else if (TrgOp.isImm()) {
39780b57cec5SDimitry Andric warnIfNoMacro(IDLoc);
39790b57cec5SDimitry Andric EmittedNoMacroWarning = true;
39800b57cec5SDimitry Andric
39810b57cec5SDimitry Andric TrgReg = getATReg(IDLoc);
39820b57cec5SDimitry Andric if (!TrgReg)
39830b57cec5SDimitry Andric return true;
39840b57cec5SDimitry Andric
39850b57cec5SDimitry Andric switch(PseudoOpcode) {
39860b57cec5SDimitry Andric default:
39870b57cec5SDimitry Andric llvm_unreachable("unknown opcode for branch pseudo-instruction");
39880b57cec5SDimitry Andric case Mips::BLTImmMacro:
39890b57cec5SDimitry Andric PseudoOpcode = Mips::BLT;
39900b57cec5SDimitry Andric break;
39910b57cec5SDimitry Andric case Mips::BLEImmMacro:
39920b57cec5SDimitry Andric PseudoOpcode = Mips::BLE;
39930b57cec5SDimitry Andric break;
39940b57cec5SDimitry Andric case Mips::BGEImmMacro:
39950b57cec5SDimitry Andric PseudoOpcode = Mips::BGE;
39960b57cec5SDimitry Andric break;
39970b57cec5SDimitry Andric case Mips::BGTImmMacro:
39980b57cec5SDimitry Andric PseudoOpcode = Mips::BGT;
39990b57cec5SDimitry Andric break;
40000b57cec5SDimitry Andric case Mips::BLTUImmMacro:
40010b57cec5SDimitry Andric PseudoOpcode = Mips::BLTU;
40020b57cec5SDimitry Andric break;
40030b57cec5SDimitry Andric case Mips::BLEUImmMacro:
40040b57cec5SDimitry Andric PseudoOpcode = Mips::BLEU;
40050b57cec5SDimitry Andric break;
40060b57cec5SDimitry Andric case Mips::BGEUImmMacro:
40070b57cec5SDimitry Andric PseudoOpcode = Mips::BGEU;
40080b57cec5SDimitry Andric break;
40090b57cec5SDimitry Andric case Mips::BGTUImmMacro:
40100b57cec5SDimitry Andric PseudoOpcode = Mips::BGTU;
40110b57cec5SDimitry Andric break;
40120b57cec5SDimitry Andric case Mips::BLTLImmMacro:
40130b57cec5SDimitry Andric PseudoOpcode = Mips::BLTL;
40140b57cec5SDimitry Andric break;
40150b57cec5SDimitry Andric case Mips::BLELImmMacro:
40160b57cec5SDimitry Andric PseudoOpcode = Mips::BLEL;
40170b57cec5SDimitry Andric break;
40180b57cec5SDimitry Andric case Mips::BGELImmMacro:
40190b57cec5SDimitry Andric PseudoOpcode = Mips::BGEL;
40200b57cec5SDimitry Andric break;
40210b57cec5SDimitry Andric case Mips::BGTLImmMacro:
40220b57cec5SDimitry Andric PseudoOpcode = Mips::BGTL;
40230b57cec5SDimitry Andric break;
40240b57cec5SDimitry Andric case Mips::BLTULImmMacro:
40250b57cec5SDimitry Andric PseudoOpcode = Mips::BLTUL;
40260b57cec5SDimitry Andric break;
40270b57cec5SDimitry Andric case Mips::BLEULImmMacro:
40280b57cec5SDimitry Andric PseudoOpcode = Mips::BLEUL;
40290b57cec5SDimitry Andric break;
40300b57cec5SDimitry Andric case Mips::BGEULImmMacro:
40310b57cec5SDimitry Andric PseudoOpcode = Mips::BGEUL;
40320b57cec5SDimitry Andric break;
40330b57cec5SDimitry Andric case Mips::BGTULImmMacro:
40340b57cec5SDimitry Andric PseudoOpcode = Mips::BGTUL;
40350b57cec5SDimitry Andric break;
40360b57cec5SDimitry Andric }
40370b57cec5SDimitry Andric
40380b57cec5SDimitry Andric if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
40390b57cec5SDimitry Andric false, IDLoc, Out, STI))
40400b57cec5SDimitry Andric return true;
40410b57cec5SDimitry Andric }
40420b57cec5SDimitry Andric
40430b57cec5SDimitry Andric switch (PseudoOpcode) {
40440b57cec5SDimitry Andric case Mips::BLT:
40450b57cec5SDimitry Andric case Mips::BLTU:
40460b57cec5SDimitry Andric case Mips::BLTL:
40470b57cec5SDimitry Andric case Mips::BLTUL:
40480b57cec5SDimitry Andric AcceptsEquality = false;
40490b57cec5SDimitry Andric ReverseOrderSLT = false;
40500b57cec5SDimitry Andric IsUnsigned =
40510b57cec5SDimitry Andric ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
40520b57cec5SDimitry Andric IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
40530b57cec5SDimitry Andric ZeroSrcOpcode = Mips::BGTZ;
40540b57cec5SDimitry Andric ZeroTrgOpcode = Mips::BLTZ;
40550b57cec5SDimitry Andric break;
40560b57cec5SDimitry Andric case Mips::BLE:
40570b57cec5SDimitry Andric case Mips::BLEU:
40580b57cec5SDimitry Andric case Mips::BLEL:
40590b57cec5SDimitry Andric case Mips::BLEUL:
40600b57cec5SDimitry Andric AcceptsEquality = true;
40610b57cec5SDimitry Andric ReverseOrderSLT = true;
40620b57cec5SDimitry Andric IsUnsigned =
40630b57cec5SDimitry Andric ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
40640b57cec5SDimitry Andric IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
40650b57cec5SDimitry Andric ZeroSrcOpcode = Mips::BGEZ;
40660b57cec5SDimitry Andric ZeroTrgOpcode = Mips::BLEZ;
40670b57cec5SDimitry Andric break;
40680b57cec5SDimitry Andric case Mips::BGE:
40690b57cec5SDimitry Andric case Mips::BGEU:
40700b57cec5SDimitry Andric case Mips::BGEL:
40710b57cec5SDimitry Andric case Mips::BGEUL:
40720b57cec5SDimitry Andric AcceptsEquality = true;
40730b57cec5SDimitry Andric ReverseOrderSLT = false;
40740b57cec5SDimitry Andric IsUnsigned =
40750b57cec5SDimitry Andric ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
40760b57cec5SDimitry Andric IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
40770b57cec5SDimitry Andric ZeroSrcOpcode = Mips::BLEZ;
40780b57cec5SDimitry Andric ZeroTrgOpcode = Mips::BGEZ;
40790b57cec5SDimitry Andric break;
40800b57cec5SDimitry Andric case Mips::BGT:
40810b57cec5SDimitry Andric case Mips::BGTU:
40820b57cec5SDimitry Andric case Mips::BGTL:
40830b57cec5SDimitry Andric case Mips::BGTUL:
40840b57cec5SDimitry Andric AcceptsEquality = false;
40850b57cec5SDimitry Andric ReverseOrderSLT = true;
40860b57cec5SDimitry Andric IsUnsigned =
40870b57cec5SDimitry Andric ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
40880b57cec5SDimitry Andric IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
40890b57cec5SDimitry Andric ZeroSrcOpcode = Mips::BLTZ;
40900b57cec5SDimitry Andric ZeroTrgOpcode = Mips::BGTZ;
40910b57cec5SDimitry Andric break;
40920b57cec5SDimitry Andric default:
40930b57cec5SDimitry Andric llvm_unreachable("unknown opcode for branch pseudo-instruction");
40940b57cec5SDimitry Andric }
40950b57cec5SDimitry Andric
40960b57cec5SDimitry Andric bool IsTrgRegZero = (TrgReg == Mips::ZERO);
40970b57cec5SDimitry Andric bool IsSrcRegZero = (SrcReg == Mips::ZERO);
40980b57cec5SDimitry Andric if (IsSrcRegZero && IsTrgRegZero) {
40990b57cec5SDimitry Andric // FIXME: All of these Opcode-specific if's are needed for compatibility
41000b57cec5SDimitry Andric // with GAS' behaviour. However, they may not generate the most efficient
41010b57cec5SDimitry Andric // code in some circumstances.
41020b57cec5SDimitry Andric if (PseudoOpcode == Mips::BLT) {
41030b57cec5SDimitry Andric TOut.emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
41040b57cec5SDimitry Andric IDLoc, STI);
41050b57cec5SDimitry Andric return false;
41060b57cec5SDimitry Andric }
41070b57cec5SDimitry Andric if (PseudoOpcode == Mips::BLE) {
41080b57cec5SDimitry Andric TOut.emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
41090b57cec5SDimitry Andric IDLoc, STI);
41100b57cec5SDimitry Andric Warning(IDLoc, "branch is always taken");
41110b57cec5SDimitry Andric return false;
41120b57cec5SDimitry Andric }
41130b57cec5SDimitry Andric if (PseudoOpcode == Mips::BGE) {
41140b57cec5SDimitry Andric TOut.emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
41150b57cec5SDimitry Andric IDLoc, STI);
41160b57cec5SDimitry Andric Warning(IDLoc, "branch is always taken");
41170b57cec5SDimitry Andric return false;
41180b57cec5SDimitry Andric }
41190b57cec5SDimitry Andric if (PseudoOpcode == Mips::BGT) {
41200b57cec5SDimitry Andric TOut.emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
41210b57cec5SDimitry Andric IDLoc, STI);
41220b57cec5SDimitry Andric return false;
41230b57cec5SDimitry Andric }
41240b57cec5SDimitry Andric if (PseudoOpcode == Mips::BGTU) {
41250b57cec5SDimitry Andric TOut.emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
41260b57cec5SDimitry Andric MCOperand::createExpr(OffsetExpr), IDLoc, STI);
41270b57cec5SDimitry Andric return false;
41280b57cec5SDimitry Andric }
41290b57cec5SDimitry Andric if (AcceptsEquality) {
41300b57cec5SDimitry Andric // If both registers are $0 and the pseudo-branch accepts equality, it
41310b57cec5SDimitry Andric // will always be taken, so we emit an unconditional branch.
41320b57cec5SDimitry Andric TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
41330b57cec5SDimitry Andric MCOperand::createExpr(OffsetExpr), IDLoc, STI);
41340b57cec5SDimitry Andric Warning(IDLoc, "branch is always taken");
41350b57cec5SDimitry Andric return false;
41360b57cec5SDimitry Andric }
41370b57cec5SDimitry Andric // If both registers are $0 and the pseudo-branch does not accept
41380b57cec5SDimitry Andric // equality, it will never be taken, so we don't have to emit anything.
41390b57cec5SDimitry Andric return false;
41400b57cec5SDimitry Andric }
41410b57cec5SDimitry Andric if (IsSrcRegZero || IsTrgRegZero) {
41420b57cec5SDimitry Andric if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
41430b57cec5SDimitry Andric (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
41440b57cec5SDimitry Andric // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
41450b57cec5SDimitry Andric // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
41460b57cec5SDimitry Andric // the pseudo-branch will never be taken, so we don't emit anything.
41470b57cec5SDimitry Andric // This only applies to unsigned pseudo-branches.
41480b57cec5SDimitry Andric return false;
41490b57cec5SDimitry Andric }
41500b57cec5SDimitry Andric if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
41510b57cec5SDimitry Andric (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
41520b57cec5SDimitry Andric // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
41530b57cec5SDimitry Andric // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
41540b57cec5SDimitry Andric // the pseudo-branch will always be taken, so we emit an unconditional
41550b57cec5SDimitry Andric // branch.
41560b57cec5SDimitry Andric // This only applies to unsigned pseudo-branches.
41570b57cec5SDimitry Andric TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
41580b57cec5SDimitry Andric MCOperand::createExpr(OffsetExpr), IDLoc, STI);
41590b57cec5SDimitry Andric Warning(IDLoc, "branch is always taken");
41600b57cec5SDimitry Andric return false;
41610b57cec5SDimitry Andric }
41620b57cec5SDimitry Andric if (IsUnsigned) {
41630b57cec5SDimitry Andric // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
41640b57cec5SDimitry Andric // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
41650b57cec5SDimitry Andric // the pseudo-branch will be taken only when the non-zero register is
41660b57cec5SDimitry Andric // different from 0, so we emit a BNEZ.
41670b57cec5SDimitry Andric //
41680b57cec5SDimitry Andric // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
41690b57cec5SDimitry Andric // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
41700b57cec5SDimitry Andric // the pseudo-branch will be taken only when the non-zero register is
41710b57cec5SDimitry Andric // equal to 0, so we emit a BEQZ.
41720b57cec5SDimitry Andric //
41730b57cec5SDimitry Andric // Because only BLEU and BGEU branch on equality, we can use the
41740b57cec5SDimitry Andric // AcceptsEquality variable to decide when to emit the BEQZ.
41750b57cec5SDimitry Andric TOut.emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
41760b57cec5SDimitry Andric IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
41770b57cec5SDimitry Andric MCOperand::createExpr(OffsetExpr), IDLoc, STI);
41780b57cec5SDimitry Andric return false;
41790b57cec5SDimitry Andric }
41800b57cec5SDimitry Andric // If we have a signed pseudo-branch and one of the registers is $0,
41810b57cec5SDimitry Andric // we can use an appropriate compare-to-zero branch. We select which one
41820b57cec5SDimitry Andric // to use in the switch statement above.
41830b57cec5SDimitry Andric TOut.emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
41840b57cec5SDimitry Andric IsSrcRegZero ? TrgReg : SrcReg,
41850b57cec5SDimitry Andric MCOperand::createExpr(OffsetExpr), IDLoc, STI);
41860b57cec5SDimitry Andric return false;
41870b57cec5SDimitry Andric }
41880b57cec5SDimitry Andric
41890b57cec5SDimitry Andric // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
41900b57cec5SDimitry Andric // expansions. If it is not available, we return.
41910b57cec5SDimitry Andric unsigned ATRegNum = getATReg(IDLoc);
41920b57cec5SDimitry Andric if (!ATRegNum)
41930b57cec5SDimitry Andric return true;
41940b57cec5SDimitry Andric
41950b57cec5SDimitry Andric if (!EmittedNoMacroWarning)
41960b57cec5SDimitry Andric warnIfNoMacro(IDLoc);
41970b57cec5SDimitry Andric
41980b57cec5SDimitry Andric // SLT fits well with 2 of our 4 pseudo-branches:
41990b57cec5SDimitry Andric // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
42000b57cec5SDimitry Andric // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
42010b57cec5SDimitry Andric // If the result of the SLT is 1, we branch, and if it's 0, we don't.
42020b57cec5SDimitry Andric // This is accomplished by using a BNEZ with the result of the SLT.
42030b57cec5SDimitry Andric //
42040b57cec5SDimitry Andric // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
42050b57cec5SDimitry Andric // and BLE with BGT), so we change the BNEZ into a BEQZ.
42060b57cec5SDimitry Andric // Because only BGE and BLE branch on equality, we can use the
42070b57cec5SDimitry Andric // AcceptsEquality variable to decide when to emit the BEQZ.
42080b57cec5SDimitry Andric // Note that the order of the SLT arguments doesn't change between
42090b57cec5SDimitry Andric // opposites.
42100b57cec5SDimitry Andric //
42110b57cec5SDimitry Andric // The same applies to the unsigned variants, except that SLTu is used
42120b57cec5SDimitry Andric // instead of SLT.
42130b57cec5SDimitry Andric TOut.emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
42140b57cec5SDimitry Andric ReverseOrderSLT ? TrgReg : SrcReg,
42150b57cec5SDimitry Andric ReverseOrderSLT ? SrcReg : TrgReg, IDLoc, STI);
42160b57cec5SDimitry Andric
42170b57cec5SDimitry Andric TOut.emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
42180b57cec5SDimitry Andric : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
42190b57cec5SDimitry Andric ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
42200b57cec5SDimitry Andric STI);
42210b57cec5SDimitry Andric return false;
42220b57cec5SDimitry Andric }
42230b57cec5SDimitry Andric
42240b57cec5SDimitry Andric // Expand a integer division macro.
42250b57cec5SDimitry Andric //
42260b57cec5SDimitry Andric // Notably we don't have to emit a warning when encountering $rt as the $zero
42270b57cec5SDimitry Andric // register, or 0 as an immediate. processInstruction() has already done that.
42280b57cec5SDimitry Andric //
42290b57cec5SDimitry Andric // The destination register can only be $zero when expanding (S)DivIMacro or
42300b57cec5SDimitry Andric // D(S)DivMacro.
42310b57cec5SDimitry Andric
expandDivRem(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI,const bool IsMips64,const bool Signed)42320b57cec5SDimitry Andric bool MipsAsmParser::expandDivRem(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4233480093f4SDimitry Andric const MCSubtargetInfo *STI,
4234480093f4SDimitry Andric const bool IsMips64, const bool Signed) {
42350b57cec5SDimitry Andric MipsTargetStreamer &TOut = getTargetStreamer();
42360b57cec5SDimitry Andric
42370b57cec5SDimitry Andric warnIfNoMacro(IDLoc);
42380b57cec5SDimitry Andric
42390b57cec5SDimitry Andric const MCOperand &RdRegOp = Inst.getOperand(0);
42400b57cec5SDimitry Andric assert(RdRegOp.isReg() && "expected register operand kind");
42410b57cec5SDimitry Andric unsigned RdReg = RdRegOp.getReg();
42420b57cec5SDimitry Andric
42430b57cec5SDimitry Andric const MCOperand &RsRegOp = Inst.getOperand(1);
42440b57cec5SDimitry Andric assert(RsRegOp.isReg() && "expected register operand kind");
42450b57cec5SDimitry Andric unsigned RsReg = RsRegOp.getReg();
42460b57cec5SDimitry Andric
42470b57cec5SDimitry Andric unsigned RtReg;
42480b57cec5SDimitry Andric int64_t ImmValue;
42490b57cec5SDimitry Andric
42500b57cec5SDimitry Andric const MCOperand &RtOp = Inst.getOperand(2);
42510b57cec5SDimitry Andric assert((RtOp.isReg() || RtOp.isImm()) &&
42520b57cec5SDimitry Andric "expected register or immediate operand kind");
42530b57cec5SDimitry Andric if (RtOp.isReg())
42540b57cec5SDimitry Andric RtReg = RtOp.getReg();
42550b57cec5SDimitry Andric else
42560b57cec5SDimitry Andric ImmValue = RtOp.getImm();
42570b57cec5SDimitry Andric
42580b57cec5SDimitry Andric unsigned DivOp;
42590b57cec5SDimitry Andric unsigned ZeroReg;
42600b57cec5SDimitry Andric unsigned SubOp;
42610b57cec5SDimitry Andric
42620b57cec5SDimitry Andric if (IsMips64) {
42630b57cec5SDimitry Andric DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
42640b57cec5SDimitry Andric ZeroReg = Mips::ZERO_64;
42650b57cec5SDimitry Andric SubOp = Mips::DSUB;
42660b57cec5SDimitry Andric } else {
42670b57cec5SDimitry Andric DivOp = Signed ? Mips::SDIV : Mips::UDIV;
42680b57cec5SDimitry Andric ZeroReg = Mips::ZERO;
42690b57cec5SDimitry Andric SubOp = Mips::SUB;
42700b57cec5SDimitry Andric }
42710b57cec5SDimitry Andric
42720b57cec5SDimitry Andric bool UseTraps = useTraps();
42730b57cec5SDimitry Andric
42740b57cec5SDimitry Andric unsigned Opcode = Inst.getOpcode();
42750b57cec5SDimitry Andric bool isDiv = Opcode == Mips::SDivMacro || Opcode == Mips::SDivIMacro ||
42760b57cec5SDimitry Andric Opcode == Mips::UDivMacro || Opcode == Mips::UDivIMacro ||
42770b57cec5SDimitry Andric Opcode == Mips::DSDivMacro || Opcode == Mips::DSDivIMacro ||
42780b57cec5SDimitry Andric Opcode == Mips::DUDivMacro || Opcode == Mips::DUDivIMacro;
42790b57cec5SDimitry Andric
42800b57cec5SDimitry Andric bool isRem = Opcode == Mips::SRemMacro || Opcode == Mips::SRemIMacro ||
42810b57cec5SDimitry Andric Opcode == Mips::URemMacro || Opcode == Mips::URemIMacro ||
42820b57cec5SDimitry Andric Opcode == Mips::DSRemMacro || Opcode == Mips::DSRemIMacro ||
42830b57cec5SDimitry Andric Opcode == Mips::DURemMacro || Opcode == Mips::DURemIMacro;
42840b57cec5SDimitry Andric
42850b57cec5SDimitry Andric if (RtOp.isImm()) {
42860b57cec5SDimitry Andric unsigned ATReg = getATReg(IDLoc);
42870b57cec5SDimitry Andric if (!ATReg)
42880b57cec5SDimitry Andric return true;
42890b57cec5SDimitry Andric
42900b57cec5SDimitry Andric if (ImmValue == 0) {
42910b57cec5SDimitry Andric if (UseTraps)
42920b57cec5SDimitry Andric TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI);
42930b57cec5SDimitry Andric else
42940b57cec5SDimitry Andric TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
42950b57cec5SDimitry Andric return false;
42960b57cec5SDimitry Andric }
42970b57cec5SDimitry Andric
42980b57cec5SDimitry Andric if (isRem && (ImmValue == 1 || (Signed && (ImmValue == -1)))) {
42990b57cec5SDimitry Andric TOut.emitRRR(Mips::OR, RdReg, ZeroReg, ZeroReg, IDLoc, STI);
43000b57cec5SDimitry Andric return false;
43010b57cec5SDimitry Andric } else if (isDiv && ImmValue == 1) {
43020b57cec5SDimitry Andric TOut.emitRRR(Mips::OR, RdReg, RsReg, Mips::ZERO, IDLoc, STI);
43030b57cec5SDimitry Andric return false;
43040b57cec5SDimitry Andric } else if (isDiv && Signed && ImmValue == -1) {
43050b57cec5SDimitry Andric TOut.emitRRR(SubOp, RdReg, ZeroReg, RsReg, IDLoc, STI);
43060b57cec5SDimitry Andric return false;
43070b57cec5SDimitry Andric } else {
43080b57cec5SDimitry Andric if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, isInt<32>(ImmValue),
43090b57cec5SDimitry Andric false, Inst.getLoc(), Out, STI))
43100b57cec5SDimitry Andric return true;
43110b57cec5SDimitry Andric TOut.emitRR(DivOp, RsReg, ATReg, IDLoc, STI);
43120b57cec5SDimitry Andric TOut.emitR(isDiv ? Mips::MFLO : Mips::MFHI, RdReg, IDLoc, STI);
43130b57cec5SDimitry Andric return false;
43140b57cec5SDimitry Andric }
43150b57cec5SDimitry Andric return true;
43160b57cec5SDimitry Andric }
43170b57cec5SDimitry Andric
43180b57cec5SDimitry Andric // If the macro expansion of (d)div(u) or (d)rem(u) would always trap or
43190b57cec5SDimitry Andric // break, insert the trap/break and exit. This gives a different result to
43200b57cec5SDimitry Andric // GAS. GAS has an inconsistency/missed optimization in that not all cases
43210b57cec5SDimitry Andric // are handled equivalently. As the observed behaviour is the same, we're ok.
43220b57cec5SDimitry Andric if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
43230b57cec5SDimitry Andric if (UseTraps) {
43240b57cec5SDimitry Andric TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI);
43250b57cec5SDimitry Andric return false;
43260b57cec5SDimitry Andric }
43270b57cec5SDimitry Andric TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
43280b57cec5SDimitry Andric return false;
43290b57cec5SDimitry Andric }
43300b57cec5SDimitry Andric
43310b57cec5SDimitry Andric // (d)rem(u) $0, $X, $Y is a special case. Like div $zero, $X, $Y, it does
43320b57cec5SDimitry Andric // not expand to macro sequence.
43330b57cec5SDimitry Andric if (isRem && (RdReg == Mips::ZERO || RdReg == Mips::ZERO_64)) {
43340b57cec5SDimitry Andric TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
43350b57cec5SDimitry Andric return false;
43360b57cec5SDimitry Andric }
43370b57cec5SDimitry Andric
43380b57cec5SDimitry Andric // Temporary label for first branch traget
43390b57cec5SDimitry Andric MCContext &Context = TOut.getStreamer().getContext();
43400b57cec5SDimitry Andric MCSymbol *BrTarget;
43410b57cec5SDimitry Andric MCOperand LabelOp;
43420b57cec5SDimitry Andric
43430b57cec5SDimitry Andric if (UseTraps) {
43440b57cec5SDimitry Andric TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
43450b57cec5SDimitry Andric } else {
43460b57cec5SDimitry Andric // Branch to the li instruction.
43470b57cec5SDimitry Andric BrTarget = Context.createTempSymbol();
43480b57cec5SDimitry Andric LabelOp = MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
43490b57cec5SDimitry Andric TOut.emitRRX(Mips::BNE, RtReg, ZeroReg, LabelOp, IDLoc, STI);
43500b57cec5SDimitry Andric }
43510b57cec5SDimitry Andric
43520b57cec5SDimitry Andric TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
43530b57cec5SDimitry Andric
43540b57cec5SDimitry Andric if (!UseTraps)
43550b57cec5SDimitry Andric TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
43560b57cec5SDimitry Andric
43570b57cec5SDimitry Andric if (!Signed) {
43580b57cec5SDimitry Andric if (!UseTraps)
43595ffd83dbSDimitry Andric TOut.getStreamer().emitLabel(BrTarget);
43600b57cec5SDimitry Andric
43610b57cec5SDimitry Andric TOut.emitR(isDiv ? Mips::MFLO : Mips::MFHI, RdReg, IDLoc, STI);
43620b57cec5SDimitry Andric return false;
43630b57cec5SDimitry Andric }
43640b57cec5SDimitry Andric
43650b57cec5SDimitry Andric unsigned ATReg = getATReg(IDLoc);
43660b57cec5SDimitry Andric if (!ATReg)
43670b57cec5SDimitry Andric return true;
43680b57cec5SDimitry Andric
43690b57cec5SDimitry Andric if (!UseTraps)
43705ffd83dbSDimitry Andric TOut.getStreamer().emitLabel(BrTarget);
43710b57cec5SDimitry Andric
43720b57cec5SDimitry Andric TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, STI);
43730b57cec5SDimitry Andric
43740b57cec5SDimitry Andric // Temporary label for the second branch target.
43750b57cec5SDimitry Andric MCSymbol *BrTargetEnd = Context.createTempSymbol();
43760b57cec5SDimitry Andric MCOperand LabelOpEnd =
43770b57cec5SDimitry Andric MCOperand::createExpr(MCSymbolRefExpr::create(BrTargetEnd, Context));
43780b57cec5SDimitry Andric
43790b57cec5SDimitry Andric // Branch to the mflo instruction.
43800b57cec5SDimitry Andric TOut.emitRRX(Mips::BNE, RtReg, ATReg, LabelOpEnd, IDLoc, STI);
43810b57cec5SDimitry Andric
43820b57cec5SDimitry Andric if (IsMips64) {
43830b57cec5SDimitry Andric TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, STI);
43840b57cec5SDimitry Andric TOut.emitDSLL(ATReg, ATReg, 63, IDLoc, STI);
43850b57cec5SDimitry Andric } else {
43860b57cec5SDimitry Andric TOut.emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, STI);
43870b57cec5SDimitry Andric }
43880b57cec5SDimitry Andric
43890b57cec5SDimitry Andric if (UseTraps)
43900b57cec5SDimitry Andric TOut.emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, STI);
43910b57cec5SDimitry Andric else {
43920b57cec5SDimitry Andric // Branch to the mflo instruction.
43930b57cec5SDimitry Andric TOut.emitRRX(Mips::BNE, RsReg, ATReg, LabelOpEnd, IDLoc, STI);
43940b57cec5SDimitry Andric TOut.emitNop(IDLoc, STI);
43950b57cec5SDimitry Andric TOut.emitII(Mips::BREAK, 0x6, 0, IDLoc, STI);
43960b57cec5SDimitry Andric }
43970b57cec5SDimitry Andric
43985ffd83dbSDimitry Andric TOut.getStreamer().emitLabel(BrTargetEnd);
43990b57cec5SDimitry Andric TOut.emitR(isDiv ? Mips::MFLO : Mips::MFHI, RdReg, IDLoc, STI);
44000b57cec5SDimitry Andric return false;
44010b57cec5SDimitry Andric }
44020b57cec5SDimitry Andric
expandTrunc(MCInst & Inst,bool IsDouble,bool Is64FPU,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)44030b57cec5SDimitry Andric bool MipsAsmParser::expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU,
44040b57cec5SDimitry Andric SMLoc IDLoc, MCStreamer &Out,
44050b57cec5SDimitry Andric const MCSubtargetInfo *STI) {
44060b57cec5SDimitry Andric MipsTargetStreamer &TOut = getTargetStreamer();
44070b57cec5SDimitry Andric
44080b57cec5SDimitry Andric assert(Inst.getNumOperands() == 3 && "Invalid operand count");
44090b57cec5SDimitry Andric assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() &&
44100b57cec5SDimitry Andric Inst.getOperand(2).isReg() && "Invalid instruction operand.");
44110b57cec5SDimitry Andric
44120b57cec5SDimitry Andric unsigned FirstReg = Inst.getOperand(0).getReg();
44130b57cec5SDimitry Andric unsigned SecondReg = Inst.getOperand(1).getReg();
44140b57cec5SDimitry Andric unsigned ThirdReg = Inst.getOperand(2).getReg();
44150b57cec5SDimitry Andric
44160b57cec5SDimitry Andric if (hasMips1() && !hasMips2()) {
44170b57cec5SDimitry Andric unsigned ATReg = getATReg(IDLoc);
44180b57cec5SDimitry Andric if (!ATReg)
44190b57cec5SDimitry Andric return true;
44200b57cec5SDimitry Andric TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
44210b57cec5SDimitry Andric TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
44220b57cec5SDimitry Andric TOut.emitNop(IDLoc, STI);
44230b57cec5SDimitry Andric TOut.emitRRI(Mips::ORi, ATReg, ThirdReg, 0x3, IDLoc, STI);
44240b57cec5SDimitry Andric TOut.emitRRI(Mips::XORi, ATReg, ATReg, 0x2, IDLoc, STI);
44250b57cec5SDimitry Andric TOut.emitRR(Mips::CTC1, Mips::RA, ATReg, IDLoc, STI);
44260b57cec5SDimitry Andric TOut.emitNop(IDLoc, STI);
44270b57cec5SDimitry Andric TOut.emitRR(IsDouble ? (Is64FPU ? Mips::CVT_W_D64 : Mips::CVT_W_D32)
44280b57cec5SDimitry Andric : Mips::CVT_W_S,
44290b57cec5SDimitry Andric FirstReg, SecondReg, IDLoc, STI);
44300b57cec5SDimitry Andric TOut.emitRR(Mips::CTC1, Mips::RA, ThirdReg, IDLoc, STI);
44310b57cec5SDimitry Andric TOut.emitNop(IDLoc, STI);
44320b57cec5SDimitry Andric return false;
44330b57cec5SDimitry Andric }
44340b57cec5SDimitry Andric
44350b57cec5SDimitry Andric TOut.emitRR(IsDouble ? (Is64FPU ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32)
44360b57cec5SDimitry Andric : Mips::TRUNC_W_S,
44370b57cec5SDimitry Andric FirstReg, SecondReg, IDLoc, STI);
44380b57cec5SDimitry Andric
44390b57cec5SDimitry Andric return false;
44400b57cec5SDimitry Andric }
44410b57cec5SDimitry Andric
expandUlh(MCInst & Inst,bool Signed,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)44420b57cec5SDimitry Andric bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
44430b57cec5SDimitry Andric MCStreamer &Out, const MCSubtargetInfo *STI) {
44440b57cec5SDimitry Andric if (hasMips32r6() || hasMips64r6()) {
44450b57cec5SDimitry Andric return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
44460b57cec5SDimitry Andric }
44470b57cec5SDimitry Andric
44480b57cec5SDimitry Andric const MCOperand &DstRegOp = Inst.getOperand(0);
44490b57cec5SDimitry Andric assert(DstRegOp.isReg() && "expected register operand kind");
44500b57cec5SDimitry Andric const MCOperand &SrcRegOp = Inst.getOperand(1);
44510b57cec5SDimitry Andric assert(SrcRegOp.isReg() && "expected register operand kind");
44520b57cec5SDimitry Andric const MCOperand &OffsetImmOp = Inst.getOperand(2);
44530b57cec5SDimitry Andric assert(OffsetImmOp.isImm() && "expected immediate operand kind");
44540b57cec5SDimitry Andric
44550b57cec5SDimitry Andric MipsTargetStreamer &TOut = getTargetStreamer();
44560b57cec5SDimitry Andric unsigned DstReg = DstRegOp.getReg();
44570b57cec5SDimitry Andric unsigned SrcReg = SrcRegOp.getReg();
44580b57cec5SDimitry Andric int64_t OffsetValue = OffsetImmOp.getImm();
44590b57cec5SDimitry Andric
44600b57cec5SDimitry Andric // NOTE: We always need AT for ULHU, as it is always used as the source
44610b57cec5SDimitry Andric // register for one of the LBu's.
44620b57cec5SDimitry Andric warnIfNoMacro(IDLoc);
44630b57cec5SDimitry Andric unsigned ATReg = getATReg(IDLoc);
44640b57cec5SDimitry Andric if (!ATReg)
44650b57cec5SDimitry Andric return true;
44660b57cec5SDimitry Andric
44670b57cec5SDimitry Andric bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue));
44680b57cec5SDimitry Andric if (IsLargeOffset) {
44690b57cec5SDimitry Andric if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true,
44700b57cec5SDimitry Andric IDLoc, Out, STI))
44710b57cec5SDimitry Andric return true;
44720b57cec5SDimitry Andric }
44730b57cec5SDimitry Andric
44740b57cec5SDimitry Andric int64_t FirstOffset = IsLargeOffset ? 0 : OffsetValue;
44750b57cec5SDimitry Andric int64_t SecondOffset = IsLargeOffset ? 1 : (OffsetValue + 1);
44760b57cec5SDimitry Andric if (isLittle())
44770b57cec5SDimitry Andric std::swap(FirstOffset, SecondOffset);
44780b57cec5SDimitry Andric
44790b57cec5SDimitry Andric unsigned FirstLbuDstReg = IsLargeOffset ? DstReg : ATReg;
44800b57cec5SDimitry Andric unsigned SecondLbuDstReg = IsLargeOffset ? ATReg : DstReg;
44810b57cec5SDimitry Andric
44820b57cec5SDimitry Andric unsigned LbuSrcReg = IsLargeOffset ? ATReg : SrcReg;
44830b57cec5SDimitry Andric unsigned SllReg = IsLargeOffset ? DstReg : ATReg;
44840b57cec5SDimitry Andric
44850b57cec5SDimitry Andric TOut.emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
44860b57cec5SDimitry Andric FirstOffset, IDLoc, STI);
44870b57cec5SDimitry Andric TOut.emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondOffset, IDLoc, STI);
44880b57cec5SDimitry Andric TOut.emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, STI);
44890b57cec5SDimitry Andric TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
44900b57cec5SDimitry Andric
44910b57cec5SDimitry Andric return false;
44920b57cec5SDimitry Andric }
44930b57cec5SDimitry Andric
expandUsh(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)44940b57cec5SDimitry Andric bool MipsAsmParser::expandUsh(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
44950b57cec5SDimitry Andric const MCSubtargetInfo *STI) {
44960b57cec5SDimitry Andric if (hasMips32r6() || hasMips64r6()) {
44970b57cec5SDimitry Andric return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
44980b57cec5SDimitry Andric }
44990b57cec5SDimitry Andric
45000b57cec5SDimitry Andric const MCOperand &DstRegOp = Inst.getOperand(0);
45010b57cec5SDimitry Andric assert(DstRegOp.isReg() && "expected register operand kind");
45020b57cec5SDimitry Andric const MCOperand &SrcRegOp = Inst.getOperand(1);
45030b57cec5SDimitry Andric assert(SrcRegOp.isReg() && "expected register operand kind");
45040b57cec5SDimitry Andric const MCOperand &OffsetImmOp = Inst.getOperand(2);
45050b57cec5SDimitry Andric assert(OffsetImmOp.isImm() && "expected immediate operand kind");
45060b57cec5SDimitry Andric
45070b57cec5SDimitry Andric MipsTargetStreamer &TOut = getTargetStreamer();
45080b57cec5SDimitry Andric unsigned DstReg = DstRegOp.getReg();
45090b57cec5SDimitry Andric unsigned SrcReg = SrcRegOp.getReg();
45100b57cec5SDimitry Andric int64_t OffsetValue = OffsetImmOp.getImm();
45110b57cec5SDimitry Andric
45120b57cec5SDimitry Andric warnIfNoMacro(IDLoc);
45130b57cec5SDimitry Andric unsigned ATReg = getATReg(IDLoc);
45140b57cec5SDimitry Andric if (!ATReg)
45150b57cec5SDimitry Andric return true;
45160b57cec5SDimitry Andric
45170b57cec5SDimitry Andric bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue));
45180b57cec5SDimitry Andric if (IsLargeOffset) {
45190b57cec5SDimitry Andric if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true,
45200b57cec5SDimitry Andric IDLoc, Out, STI))
45210b57cec5SDimitry Andric return true;
45220b57cec5SDimitry Andric }
45230b57cec5SDimitry Andric
45240b57cec5SDimitry Andric int64_t FirstOffset = IsLargeOffset ? 1 : (OffsetValue + 1);
45250b57cec5SDimitry Andric int64_t SecondOffset = IsLargeOffset ? 0 : OffsetValue;
45260b57cec5SDimitry Andric if (isLittle())
45270b57cec5SDimitry Andric std::swap(FirstOffset, SecondOffset);
45280b57cec5SDimitry Andric
45290b57cec5SDimitry Andric if (IsLargeOffset) {
45300b57cec5SDimitry Andric TOut.emitRRI(Mips::SB, DstReg, ATReg, FirstOffset, IDLoc, STI);
45310b57cec5SDimitry Andric TOut.emitRRI(Mips::SRL, DstReg, DstReg, 8, IDLoc, STI);
45320b57cec5SDimitry Andric TOut.emitRRI(Mips::SB, DstReg, ATReg, SecondOffset, IDLoc, STI);
45330b57cec5SDimitry Andric TOut.emitRRI(Mips::LBu, ATReg, ATReg, 0, IDLoc, STI);
45340b57cec5SDimitry Andric TOut.emitRRI(Mips::SLL, DstReg, DstReg, 8, IDLoc, STI);
45350b57cec5SDimitry Andric TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
45360b57cec5SDimitry Andric } else {
45370b57cec5SDimitry Andric TOut.emitRRI(Mips::SB, DstReg, SrcReg, FirstOffset, IDLoc, STI);
45380b57cec5SDimitry Andric TOut.emitRRI(Mips::SRL, ATReg, DstReg, 8, IDLoc, STI);
45390b57cec5SDimitry Andric TOut.emitRRI(Mips::SB, ATReg, SrcReg, SecondOffset, IDLoc, STI);
45400b57cec5SDimitry Andric }
45410b57cec5SDimitry Andric
45420b57cec5SDimitry Andric return false;
45430b57cec5SDimitry Andric }
45440b57cec5SDimitry Andric
expandUxw(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)45450b57cec5SDimitry Andric bool MipsAsmParser::expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
45460b57cec5SDimitry Andric const MCSubtargetInfo *STI) {
45470b57cec5SDimitry Andric if (hasMips32r6() || hasMips64r6()) {
45480b57cec5SDimitry Andric return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
45490b57cec5SDimitry Andric }
45500b57cec5SDimitry Andric
45510b57cec5SDimitry Andric const MCOperand &DstRegOp = Inst.getOperand(0);
45520b57cec5SDimitry Andric assert(DstRegOp.isReg() && "expected register operand kind");
45530b57cec5SDimitry Andric const MCOperand &SrcRegOp = Inst.getOperand(1);
45540b57cec5SDimitry Andric assert(SrcRegOp.isReg() && "expected register operand kind");
45550b57cec5SDimitry Andric const MCOperand &OffsetImmOp = Inst.getOperand(2);
45560b57cec5SDimitry Andric assert(OffsetImmOp.isImm() && "expected immediate operand kind");
45570b57cec5SDimitry Andric
45580b57cec5SDimitry Andric MipsTargetStreamer &TOut = getTargetStreamer();
45590b57cec5SDimitry Andric unsigned DstReg = DstRegOp.getReg();
45600b57cec5SDimitry Andric unsigned SrcReg = SrcRegOp.getReg();
45610b57cec5SDimitry Andric int64_t OffsetValue = OffsetImmOp.getImm();
45620b57cec5SDimitry Andric
45630b57cec5SDimitry Andric // Compute left/right load/store offsets.
45640b57cec5SDimitry Andric bool IsLargeOffset = !(isInt<16>(OffsetValue + 3) && isInt<16>(OffsetValue));
45650b57cec5SDimitry Andric int64_t LxlOffset = IsLargeOffset ? 0 : OffsetValue;
45660b57cec5SDimitry Andric int64_t LxrOffset = IsLargeOffset ? 3 : (OffsetValue + 3);
45670b57cec5SDimitry Andric if (isLittle())
45680b57cec5SDimitry Andric std::swap(LxlOffset, LxrOffset);
45690b57cec5SDimitry Andric
45700b57cec5SDimitry Andric bool IsLoadInst = (Inst.getOpcode() == Mips::Ulw);
45710b57cec5SDimitry Andric bool DoMove = IsLoadInst && (SrcReg == DstReg) && !IsLargeOffset;
45720b57cec5SDimitry Andric unsigned TmpReg = SrcReg;
45730b57cec5SDimitry Andric if (IsLargeOffset || DoMove) {
45740b57cec5SDimitry Andric warnIfNoMacro(IDLoc);
45750b57cec5SDimitry Andric TmpReg = getATReg(IDLoc);
45760b57cec5SDimitry Andric if (!TmpReg)
45770b57cec5SDimitry Andric return true;
45780b57cec5SDimitry Andric }
45790b57cec5SDimitry Andric
45800b57cec5SDimitry Andric if (IsLargeOffset) {
45810b57cec5SDimitry Andric if (loadImmediate(OffsetValue, TmpReg, SrcReg, !ABI.ArePtrs64bit(), true,
45820b57cec5SDimitry Andric IDLoc, Out, STI))
45830b57cec5SDimitry Andric return true;
45840b57cec5SDimitry Andric }
45850b57cec5SDimitry Andric
45860b57cec5SDimitry Andric if (DoMove)
45870b57cec5SDimitry Andric std::swap(DstReg, TmpReg);
45880b57cec5SDimitry Andric
45890b57cec5SDimitry Andric unsigned XWL = IsLoadInst ? Mips::LWL : Mips::SWL;
45900b57cec5SDimitry Andric unsigned XWR = IsLoadInst ? Mips::LWR : Mips::SWR;
45910b57cec5SDimitry Andric TOut.emitRRI(XWL, DstReg, TmpReg, LxlOffset, IDLoc, STI);
45920b57cec5SDimitry Andric TOut.emitRRI(XWR, DstReg, TmpReg, LxrOffset, IDLoc, STI);
45930b57cec5SDimitry Andric
45940b57cec5SDimitry Andric if (DoMove)
45950b57cec5SDimitry Andric TOut.emitRRR(Mips::OR, TmpReg, DstReg, Mips::ZERO, IDLoc, STI);
45960b57cec5SDimitry Andric
45970b57cec5SDimitry Andric return false;
45980b57cec5SDimitry Andric }
45990b57cec5SDimitry Andric
expandSge(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)46000b57cec5SDimitry Andric bool MipsAsmParser::expandSge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
46010b57cec5SDimitry Andric const MCSubtargetInfo *STI) {
46020b57cec5SDimitry Andric MipsTargetStreamer &TOut = getTargetStreamer();
46030b57cec5SDimitry Andric
46040b57cec5SDimitry Andric assert(Inst.getNumOperands() == 3 && "Invalid operand count");
46050b57cec5SDimitry Andric assert(Inst.getOperand(0).isReg() &&
46060b57cec5SDimitry Andric Inst.getOperand(1).isReg() &&
46070b57cec5SDimitry Andric Inst.getOperand(2).isReg() && "Invalid instruction operand.");
46080b57cec5SDimitry Andric
46090b57cec5SDimitry Andric unsigned DstReg = Inst.getOperand(0).getReg();
46100b57cec5SDimitry Andric unsigned SrcReg = Inst.getOperand(1).getReg();
46110b57cec5SDimitry Andric unsigned OpReg = Inst.getOperand(2).getReg();
46120b57cec5SDimitry Andric unsigned OpCode;
46130b57cec5SDimitry Andric
46140b57cec5SDimitry Andric warnIfNoMacro(IDLoc);
46150b57cec5SDimitry Andric
46160b57cec5SDimitry Andric switch (Inst.getOpcode()) {
46170b57cec5SDimitry Andric case Mips::SGE:
46180b57cec5SDimitry Andric OpCode = Mips::SLT;
46190b57cec5SDimitry Andric break;
46200b57cec5SDimitry Andric case Mips::SGEU:
46210b57cec5SDimitry Andric OpCode = Mips::SLTu;
46220b57cec5SDimitry Andric break;
46230b57cec5SDimitry Andric default:
46240b57cec5SDimitry Andric llvm_unreachable("unexpected 'sge' opcode");
46250b57cec5SDimitry Andric }
46260b57cec5SDimitry Andric
46270b57cec5SDimitry Andric // $SrcReg >= $OpReg is equal to (not ($SrcReg < $OpReg))
46280b57cec5SDimitry Andric TOut.emitRRR(OpCode, DstReg, SrcReg, OpReg, IDLoc, STI);
46290b57cec5SDimitry Andric TOut.emitRRI(Mips::XORi, DstReg, DstReg, 1, IDLoc, STI);
46300b57cec5SDimitry Andric
46310b57cec5SDimitry Andric return false;
46320b57cec5SDimitry Andric }
46330b57cec5SDimitry Andric
expandSgeImm(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)46340b57cec5SDimitry Andric bool MipsAsmParser::expandSgeImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
46350b57cec5SDimitry Andric const MCSubtargetInfo *STI) {
46360b57cec5SDimitry Andric MipsTargetStreamer &TOut = getTargetStreamer();
46370b57cec5SDimitry Andric
46380b57cec5SDimitry Andric assert(Inst.getNumOperands() == 3 && "Invalid operand count");
46390b57cec5SDimitry Andric assert(Inst.getOperand(0).isReg() &&
46400b57cec5SDimitry Andric Inst.getOperand(1).isReg() &&
46410b57cec5SDimitry Andric Inst.getOperand(2).isImm() && "Invalid instruction operand.");
46420b57cec5SDimitry Andric
46430b57cec5SDimitry Andric unsigned DstReg = Inst.getOperand(0).getReg();
46440b57cec5SDimitry Andric unsigned SrcReg = Inst.getOperand(1).getReg();
46450b57cec5SDimitry Andric int64_t ImmValue = Inst.getOperand(2).getImm();
46460b57cec5SDimitry Andric unsigned OpRegCode, OpImmCode;
46470b57cec5SDimitry Andric
46480b57cec5SDimitry Andric warnIfNoMacro(IDLoc);
46490b57cec5SDimitry Andric
46500b57cec5SDimitry Andric switch (Inst.getOpcode()) {
46510b57cec5SDimitry Andric case Mips::SGEImm:
46520b57cec5SDimitry Andric case Mips::SGEImm64:
46530b57cec5SDimitry Andric OpRegCode = Mips::SLT;
46540b57cec5SDimitry Andric OpImmCode = Mips::SLTi;
46550b57cec5SDimitry Andric break;
46560b57cec5SDimitry Andric case Mips::SGEUImm:
46570b57cec5SDimitry Andric case Mips::SGEUImm64:
46580b57cec5SDimitry Andric OpRegCode = Mips::SLTu;
46590b57cec5SDimitry Andric OpImmCode = Mips::SLTiu;
46600b57cec5SDimitry Andric break;
46610b57cec5SDimitry Andric default:
46620b57cec5SDimitry Andric llvm_unreachable("unexpected 'sge' opcode with immediate");
46630b57cec5SDimitry Andric }
46640b57cec5SDimitry Andric
46650b57cec5SDimitry Andric // $SrcReg >= Imm is equal to (not ($SrcReg < Imm))
46660b57cec5SDimitry Andric if (isInt<16>(ImmValue)) {
46670b57cec5SDimitry Andric // Use immediate version of STL.
46680b57cec5SDimitry Andric TOut.emitRRI(OpImmCode, DstReg, SrcReg, ImmValue, IDLoc, STI);
46690b57cec5SDimitry Andric TOut.emitRRI(Mips::XORi, DstReg, DstReg, 1, IDLoc, STI);
46700b57cec5SDimitry Andric } else {
46710b57cec5SDimitry Andric unsigned ImmReg = DstReg;
46720b57cec5SDimitry Andric if (DstReg == SrcReg) {
46730b57cec5SDimitry Andric unsigned ATReg = getATReg(Inst.getLoc());
46740b57cec5SDimitry Andric if (!ATReg)
46750b57cec5SDimitry Andric return true;
46760b57cec5SDimitry Andric ImmReg = ATReg;
46770b57cec5SDimitry Andric }
46780b57cec5SDimitry Andric
46790b57cec5SDimitry Andric if (loadImmediate(ImmValue, ImmReg, Mips::NoRegister, isInt<32>(ImmValue),
46800b57cec5SDimitry Andric false, IDLoc, Out, STI))
46810b57cec5SDimitry Andric return true;
46820b57cec5SDimitry Andric
46830b57cec5SDimitry Andric TOut.emitRRR(OpRegCode, DstReg, SrcReg, ImmReg, IDLoc, STI);
46840b57cec5SDimitry Andric TOut.emitRRI(Mips::XORi, DstReg, DstReg, 1, IDLoc, STI);
46850b57cec5SDimitry Andric }
46860b57cec5SDimitry Andric
46870b57cec5SDimitry Andric return false;
46880b57cec5SDimitry Andric }
46890b57cec5SDimitry Andric
expandSgtImm(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)46900b57cec5SDimitry Andric bool MipsAsmParser::expandSgtImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
46910b57cec5SDimitry Andric const MCSubtargetInfo *STI) {
46920b57cec5SDimitry Andric MipsTargetStreamer &TOut = getTargetStreamer();
46930b57cec5SDimitry Andric
46940b57cec5SDimitry Andric assert(Inst.getNumOperands() == 3 && "Invalid operand count");
46950b57cec5SDimitry Andric assert(Inst.getOperand(0).isReg() &&
46960b57cec5SDimitry Andric Inst.getOperand(1).isReg() &&
46970b57cec5SDimitry Andric Inst.getOperand(2).isImm() && "Invalid instruction operand.");
46980b57cec5SDimitry Andric
46990b57cec5SDimitry Andric unsigned DstReg = Inst.getOperand(0).getReg();
47000b57cec5SDimitry Andric unsigned SrcReg = Inst.getOperand(1).getReg();
47010b57cec5SDimitry Andric unsigned ImmReg = DstReg;
47020b57cec5SDimitry Andric int64_t ImmValue = Inst.getOperand(2).getImm();
47030b57cec5SDimitry Andric unsigned OpCode;
47040b57cec5SDimitry Andric
47050b57cec5SDimitry Andric warnIfNoMacro(IDLoc);
47060b57cec5SDimitry Andric
47070b57cec5SDimitry Andric switch (Inst.getOpcode()) {
47080b57cec5SDimitry Andric case Mips::SGTImm:
47090b57cec5SDimitry Andric case Mips::SGTImm64:
47100b57cec5SDimitry Andric OpCode = Mips::SLT;
47110b57cec5SDimitry Andric break;
47120b57cec5SDimitry Andric case Mips::SGTUImm:
47130b57cec5SDimitry Andric case Mips::SGTUImm64:
47140b57cec5SDimitry Andric OpCode = Mips::SLTu;
47150b57cec5SDimitry Andric break;
47160b57cec5SDimitry Andric default:
47170b57cec5SDimitry Andric llvm_unreachable("unexpected 'sgt' opcode with immediate");
47180b57cec5SDimitry Andric }
47190b57cec5SDimitry Andric
47200b57cec5SDimitry Andric if (DstReg == SrcReg) {
47210b57cec5SDimitry Andric unsigned ATReg = getATReg(Inst.getLoc());
47220b57cec5SDimitry Andric if (!ATReg)
47230b57cec5SDimitry Andric return true;
47240b57cec5SDimitry Andric ImmReg = ATReg;
47250b57cec5SDimitry Andric }
47260b57cec5SDimitry Andric
47270b57cec5SDimitry Andric if (loadImmediate(ImmValue, ImmReg, Mips::NoRegister, isInt<32>(ImmValue),
47280b57cec5SDimitry Andric false, IDLoc, Out, STI))
47290b57cec5SDimitry Andric return true;
47300b57cec5SDimitry Andric
47310b57cec5SDimitry Andric // $SrcReg > $ImmReg is equal to $ImmReg < $SrcReg
47320b57cec5SDimitry Andric TOut.emitRRR(OpCode, DstReg, ImmReg, SrcReg, IDLoc, STI);
47330b57cec5SDimitry Andric
47340b57cec5SDimitry Andric return false;
47350b57cec5SDimitry Andric }
47360b57cec5SDimitry Andric
expandSle(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)47375ffd83dbSDimitry Andric bool MipsAsmParser::expandSle(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
47385ffd83dbSDimitry Andric const MCSubtargetInfo *STI) {
47395ffd83dbSDimitry Andric MipsTargetStreamer &TOut = getTargetStreamer();
47405ffd83dbSDimitry Andric
47415ffd83dbSDimitry Andric assert(Inst.getNumOperands() == 3 && "Invalid operand count");
47425ffd83dbSDimitry Andric assert(Inst.getOperand(0).isReg() &&
47435ffd83dbSDimitry Andric Inst.getOperand(1).isReg() &&
47445ffd83dbSDimitry Andric Inst.getOperand(2).isReg() && "Invalid instruction operand.");
47455ffd83dbSDimitry Andric
47465ffd83dbSDimitry Andric unsigned DstReg = Inst.getOperand(0).getReg();
47475ffd83dbSDimitry Andric unsigned SrcReg = Inst.getOperand(1).getReg();
47485ffd83dbSDimitry Andric unsigned OpReg = Inst.getOperand(2).getReg();
47495ffd83dbSDimitry Andric unsigned OpCode;
47505ffd83dbSDimitry Andric
47515ffd83dbSDimitry Andric warnIfNoMacro(IDLoc);
47525ffd83dbSDimitry Andric
47535ffd83dbSDimitry Andric switch (Inst.getOpcode()) {
47545ffd83dbSDimitry Andric case Mips::SLE:
47555ffd83dbSDimitry Andric OpCode = Mips::SLT;
47565ffd83dbSDimitry Andric break;
47575ffd83dbSDimitry Andric case Mips::SLEU:
47585ffd83dbSDimitry Andric OpCode = Mips::SLTu;
47595ffd83dbSDimitry Andric break;
47605ffd83dbSDimitry Andric default:
47615ffd83dbSDimitry Andric llvm_unreachable("unexpected 'sge' opcode");
47625ffd83dbSDimitry Andric }
47635ffd83dbSDimitry Andric
47645ffd83dbSDimitry Andric // $SrcReg <= $OpReg is equal to (not ($OpReg < $SrcReg))
47655ffd83dbSDimitry Andric TOut.emitRRR(OpCode, DstReg, OpReg, SrcReg, IDLoc, STI);
47665ffd83dbSDimitry Andric TOut.emitRRI(Mips::XORi, DstReg, DstReg, 1, IDLoc, STI);
47675ffd83dbSDimitry Andric
47685ffd83dbSDimitry Andric return false;
47695ffd83dbSDimitry Andric }
47705ffd83dbSDimitry Andric
expandSleImm(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)47715ffd83dbSDimitry Andric bool MipsAsmParser::expandSleImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
47725ffd83dbSDimitry Andric const MCSubtargetInfo *STI) {
47735ffd83dbSDimitry Andric MipsTargetStreamer &TOut = getTargetStreamer();
47745ffd83dbSDimitry Andric
47755ffd83dbSDimitry Andric assert(Inst.getNumOperands() == 3 && "Invalid operand count");
47765ffd83dbSDimitry Andric assert(Inst.getOperand(0).isReg() &&
47775ffd83dbSDimitry Andric Inst.getOperand(1).isReg() &&
47785ffd83dbSDimitry Andric Inst.getOperand(2).isImm() && "Invalid instruction operand.");
47795ffd83dbSDimitry Andric
47805ffd83dbSDimitry Andric unsigned DstReg = Inst.getOperand(0).getReg();
47815ffd83dbSDimitry Andric unsigned SrcReg = Inst.getOperand(1).getReg();
47825ffd83dbSDimitry Andric int64_t ImmValue = Inst.getOperand(2).getImm();
47835ffd83dbSDimitry Andric unsigned OpRegCode;
47845ffd83dbSDimitry Andric
47855ffd83dbSDimitry Andric warnIfNoMacro(IDLoc);
47865ffd83dbSDimitry Andric
47875ffd83dbSDimitry Andric switch (Inst.getOpcode()) {
47885ffd83dbSDimitry Andric case Mips::SLEImm:
47895ffd83dbSDimitry Andric case Mips::SLEImm64:
47905ffd83dbSDimitry Andric OpRegCode = Mips::SLT;
47915ffd83dbSDimitry Andric break;
47925ffd83dbSDimitry Andric case Mips::SLEUImm:
47935ffd83dbSDimitry Andric case Mips::SLEUImm64:
47945ffd83dbSDimitry Andric OpRegCode = Mips::SLTu;
47955ffd83dbSDimitry Andric break;
47965ffd83dbSDimitry Andric default:
47975ffd83dbSDimitry Andric llvm_unreachable("unexpected 'sge' opcode with immediate");
47985ffd83dbSDimitry Andric }
47995ffd83dbSDimitry Andric
48005ffd83dbSDimitry Andric // $SrcReg <= Imm is equal to (not (Imm < $SrcReg))
48015ffd83dbSDimitry Andric unsigned ImmReg = DstReg;
48025ffd83dbSDimitry Andric if (DstReg == SrcReg) {
48035ffd83dbSDimitry Andric unsigned ATReg = getATReg(Inst.getLoc());
48045ffd83dbSDimitry Andric if (!ATReg)
48055ffd83dbSDimitry Andric return true;
48065ffd83dbSDimitry Andric ImmReg = ATReg;
48075ffd83dbSDimitry Andric }
48085ffd83dbSDimitry Andric
48095ffd83dbSDimitry Andric if (loadImmediate(ImmValue, ImmReg, Mips::NoRegister, isInt<32>(ImmValue),
48105ffd83dbSDimitry Andric false, IDLoc, Out, STI))
48115ffd83dbSDimitry Andric return true;
48125ffd83dbSDimitry Andric
48135ffd83dbSDimitry Andric TOut.emitRRR(OpRegCode, DstReg, ImmReg, SrcReg, IDLoc, STI);
48145ffd83dbSDimitry Andric TOut.emitRRI(Mips::XORi, DstReg, DstReg, 1, IDLoc, STI);
48155ffd83dbSDimitry Andric
48165ffd83dbSDimitry Andric return false;
48175ffd83dbSDimitry Andric }
48185ffd83dbSDimitry Andric
expandAliasImmediate(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)48190b57cec5SDimitry Andric bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
48200b57cec5SDimitry Andric MCStreamer &Out,
48210b57cec5SDimitry Andric const MCSubtargetInfo *STI) {
48220b57cec5SDimitry Andric MipsTargetStreamer &TOut = getTargetStreamer();
48230b57cec5SDimitry Andric
48240b57cec5SDimitry Andric assert(Inst.getNumOperands() == 3 && "Invalid operand count");
48250b57cec5SDimitry Andric assert(Inst.getOperand(0).isReg() &&
48260b57cec5SDimitry Andric Inst.getOperand(1).isReg() &&
48270b57cec5SDimitry Andric Inst.getOperand(2).isImm() && "Invalid instruction operand.");
48280b57cec5SDimitry Andric
48290b57cec5SDimitry Andric unsigned ATReg = Mips::NoRegister;
48300b57cec5SDimitry Andric unsigned FinalDstReg = Mips::NoRegister;
48310b57cec5SDimitry Andric unsigned DstReg = Inst.getOperand(0).getReg();
48320b57cec5SDimitry Andric unsigned SrcReg = Inst.getOperand(1).getReg();
48330b57cec5SDimitry Andric int64_t ImmValue = Inst.getOperand(2).getImm();
48340b57cec5SDimitry Andric
48350b57cec5SDimitry Andric bool Is32Bit = isInt<32>(ImmValue) || (!isGP64bit() && isUInt<32>(ImmValue));
48360b57cec5SDimitry Andric
48370b57cec5SDimitry Andric unsigned FinalOpcode = Inst.getOpcode();
48380b57cec5SDimitry Andric
48390b57cec5SDimitry Andric if (DstReg == SrcReg) {
48400b57cec5SDimitry Andric ATReg = getATReg(Inst.getLoc());
48410b57cec5SDimitry Andric if (!ATReg)
48420b57cec5SDimitry Andric return true;
48430b57cec5SDimitry Andric FinalDstReg = DstReg;
48440b57cec5SDimitry Andric DstReg = ATReg;
48450b57cec5SDimitry Andric }
48460b57cec5SDimitry Andric
48470b57cec5SDimitry Andric if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false,
48480b57cec5SDimitry Andric Inst.getLoc(), Out, STI)) {
48490b57cec5SDimitry Andric switch (FinalOpcode) {
48500b57cec5SDimitry Andric default:
48510b57cec5SDimitry Andric llvm_unreachable("unimplemented expansion");
48520b57cec5SDimitry Andric case Mips::ADDi:
48530b57cec5SDimitry Andric FinalOpcode = Mips::ADD;
48540b57cec5SDimitry Andric break;
48550b57cec5SDimitry Andric case Mips::ADDiu:
48560b57cec5SDimitry Andric FinalOpcode = Mips::ADDu;
48570b57cec5SDimitry Andric break;
48580b57cec5SDimitry Andric case Mips::ANDi:
48590b57cec5SDimitry Andric FinalOpcode = Mips::AND;
48600b57cec5SDimitry Andric break;
48610b57cec5SDimitry Andric case Mips::NORImm:
48620b57cec5SDimitry Andric FinalOpcode = Mips::NOR;
48630b57cec5SDimitry Andric break;
48640b57cec5SDimitry Andric case Mips::ORi:
48650b57cec5SDimitry Andric FinalOpcode = Mips::OR;
48660b57cec5SDimitry Andric break;
48670b57cec5SDimitry Andric case Mips::SLTi:
48680b57cec5SDimitry Andric FinalOpcode = Mips::SLT;
48690b57cec5SDimitry Andric break;
48700b57cec5SDimitry Andric case Mips::SLTiu:
48710b57cec5SDimitry Andric FinalOpcode = Mips::SLTu;
48720b57cec5SDimitry Andric break;
48730b57cec5SDimitry Andric case Mips::XORi:
48740b57cec5SDimitry Andric FinalOpcode = Mips::XOR;
48750b57cec5SDimitry Andric break;
48760b57cec5SDimitry Andric case Mips::ADDi_MM:
48770b57cec5SDimitry Andric FinalOpcode = Mips::ADD_MM;
48780b57cec5SDimitry Andric break;
48790b57cec5SDimitry Andric case Mips::ADDiu_MM:
48800b57cec5SDimitry Andric FinalOpcode = Mips::ADDu_MM;
48810b57cec5SDimitry Andric break;
48820b57cec5SDimitry Andric case Mips::ANDi_MM:
48830b57cec5SDimitry Andric FinalOpcode = Mips::AND_MM;
48840b57cec5SDimitry Andric break;
48850b57cec5SDimitry Andric case Mips::ORi_MM:
48860b57cec5SDimitry Andric FinalOpcode = Mips::OR_MM;
48870b57cec5SDimitry Andric break;
48880b57cec5SDimitry Andric case Mips::SLTi_MM:
48890b57cec5SDimitry Andric FinalOpcode = Mips::SLT_MM;
48900b57cec5SDimitry Andric break;
48910b57cec5SDimitry Andric case Mips::SLTiu_MM:
48920b57cec5SDimitry Andric FinalOpcode = Mips::SLTu_MM;
48930b57cec5SDimitry Andric break;
48940b57cec5SDimitry Andric case Mips::XORi_MM:
48950b57cec5SDimitry Andric FinalOpcode = Mips::XOR_MM;
48960b57cec5SDimitry Andric break;
48970b57cec5SDimitry Andric case Mips::ANDi64:
48980b57cec5SDimitry Andric FinalOpcode = Mips::AND64;
48990b57cec5SDimitry Andric break;
49000b57cec5SDimitry Andric case Mips::NORImm64:
49010b57cec5SDimitry Andric FinalOpcode = Mips::NOR64;
49020b57cec5SDimitry Andric break;
49030b57cec5SDimitry Andric case Mips::ORi64:
49040b57cec5SDimitry Andric FinalOpcode = Mips::OR64;
49050b57cec5SDimitry Andric break;
49060b57cec5SDimitry Andric case Mips::SLTImm64:
49070b57cec5SDimitry Andric FinalOpcode = Mips::SLT64;
49080b57cec5SDimitry Andric break;
49090b57cec5SDimitry Andric case Mips::SLTUImm64:
49100b57cec5SDimitry Andric FinalOpcode = Mips::SLTu64;
49110b57cec5SDimitry Andric break;
49120b57cec5SDimitry Andric case Mips::XORi64:
49130b57cec5SDimitry Andric FinalOpcode = Mips::XOR64;
49140b57cec5SDimitry Andric break;
49150b57cec5SDimitry Andric }
49160b57cec5SDimitry Andric
49170b57cec5SDimitry Andric if (FinalDstReg == Mips::NoRegister)
49180b57cec5SDimitry Andric TOut.emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, STI);
49190b57cec5SDimitry Andric else
49200b57cec5SDimitry Andric TOut.emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc, STI);
49210b57cec5SDimitry Andric return false;
49220b57cec5SDimitry Andric }
49230b57cec5SDimitry Andric return true;
49240b57cec5SDimitry Andric }
49250b57cec5SDimitry Andric
expandRotation(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)49260b57cec5SDimitry Andric bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
49270b57cec5SDimitry Andric const MCSubtargetInfo *STI) {
49280b57cec5SDimitry Andric MipsTargetStreamer &TOut = getTargetStreamer();
49290b57cec5SDimitry Andric unsigned ATReg = Mips::NoRegister;
49300b57cec5SDimitry Andric unsigned DReg = Inst.getOperand(0).getReg();
49310b57cec5SDimitry Andric unsigned SReg = Inst.getOperand(1).getReg();
49320b57cec5SDimitry Andric unsigned TReg = Inst.getOperand(2).getReg();
49330b57cec5SDimitry Andric unsigned TmpReg = DReg;
49340b57cec5SDimitry Andric
49350b57cec5SDimitry Andric unsigned FirstShift = Mips::NOP;
49360b57cec5SDimitry Andric unsigned SecondShift = Mips::NOP;
49370b57cec5SDimitry Andric
49380b57cec5SDimitry Andric if (hasMips32r2()) {
49390b57cec5SDimitry Andric if (DReg == SReg) {
49400b57cec5SDimitry Andric TmpReg = getATReg(Inst.getLoc());
49410b57cec5SDimitry Andric if (!TmpReg)
49420b57cec5SDimitry Andric return true;
49430b57cec5SDimitry Andric }
49440b57cec5SDimitry Andric
49450b57cec5SDimitry Andric if (Inst.getOpcode() == Mips::ROL) {
49460b57cec5SDimitry Andric TOut.emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
49470b57cec5SDimitry Andric TOut.emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
49480b57cec5SDimitry Andric return false;
49490b57cec5SDimitry Andric }
49500b57cec5SDimitry Andric
49510b57cec5SDimitry Andric if (Inst.getOpcode() == Mips::ROR) {
49520b57cec5SDimitry Andric TOut.emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
49530b57cec5SDimitry Andric return false;
49540b57cec5SDimitry Andric }
49550b57cec5SDimitry Andric
49560b57cec5SDimitry Andric return true;
49570b57cec5SDimitry Andric }
49580b57cec5SDimitry Andric
49590b57cec5SDimitry Andric if (hasMips32()) {
49600b57cec5SDimitry Andric switch (Inst.getOpcode()) {
49610b57cec5SDimitry Andric default:
49620b57cec5SDimitry Andric llvm_unreachable("unexpected instruction opcode");
49630b57cec5SDimitry Andric case Mips::ROL:
49640b57cec5SDimitry Andric FirstShift = Mips::SRLV;
49650b57cec5SDimitry Andric SecondShift = Mips::SLLV;
49660b57cec5SDimitry Andric break;
49670b57cec5SDimitry Andric case Mips::ROR:
49680b57cec5SDimitry Andric FirstShift = Mips::SLLV;
49690b57cec5SDimitry Andric SecondShift = Mips::SRLV;
49700b57cec5SDimitry Andric break;
49710b57cec5SDimitry Andric }
49720b57cec5SDimitry Andric
49730b57cec5SDimitry Andric ATReg = getATReg(Inst.getLoc());
49740b57cec5SDimitry Andric if (!ATReg)
49750b57cec5SDimitry Andric return true;
49760b57cec5SDimitry Andric
49770b57cec5SDimitry Andric TOut.emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
49780b57cec5SDimitry Andric TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
49790b57cec5SDimitry Andric TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
49800b57cec5SDimitry Andric TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
49810b57cec5SDimitry Andric
49820b57cec5SDimitry Andric return false;
49830b57cec5SDimitry Andric }
49840b57cec5SDimitry Andric
49850b57cec5SDimitry Andric return true;
49860b57cec5SDimitry Andric }
49870b57cec5SDimitry Andric
expandRotationImm(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)49880b57cec5SDimitry Andric bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
49890b57cec5SDimitry Andric MCStreamer &Out,
49900b57cec5SDimitry Andric const MCSubtargetInfo *STI) {
49910b57cec5SDimitry Andric MipsTargetStreamer &TOut = getTargetStreamer();
49920b57cec5SDimitry Andric unsigned ATReg = Mips::NoRegister;
49930b57cec5SDimitry Andric unsigned DReg = Inst.getOperand(0).getReg();
49940b57cec5SDimitry Andric unsigned SReg = Inst.getOperand(1).getReg();
49950b57cec5SDimitry Andric int64_t ImmValue = Inst.getOperand(2).getImm();
49960b57cec5SDimitry Andric
49970b57cec5SDimitry Andric unsigned FirstShift = Mips::NOP;
49980b57cec5SDimitry Andric unsigned SecondShift = Mips::NOP;
49990b57cec5SDimitry Andric
50000b57cec5SDimitry Andric if (hasMips32r2()) {
50010b57cec5SDimitry Andric if (Inst.getOpcode() == Mips::ROLImm) {
50020b57cec5SDimitry Andric uint64_t MaxShift = 32;
50030b57cec5SDimitry Andric uint64_t ShiftValue = ImmValue;
50040b57cec5SDimitry Andric if (ImmValue != 0)
50050b57cec5SDimitry Andric ShiftValue = MaxShift - ImmValue;
50060b57cec5SDimitry Andric TOut.emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
50070b57cec5SDimitry Andric return false;
50080b57cec5SDimitry Andric }
50090b57cec5SDimitry Andric
50100b57cec5SDimitry Andric if (Inst.getOpcode() == Mips::RORImm) {
50110b57cec5SDimitry Andric TOut.emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), STI);
50120b57cec5SDimitry Andric return false;
50130b57cec5SDimitry Andric }
50140b57cec5SDimitry Andric
50150b57cec5SDimitry Andric return true;
50160b57cec5SDimitry Andric }
50170b57cec5SDimitry Andric
50180b57cec5SDimitry Andric if (hasMips32()) {
50190b57cec5SDimitry Andric if (ImmValue == 0) {
50200b57cec5SDimitry Andric TOut.emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), STI);
50210b57cec5SDimitry Andric return false;
50220b57cec5SDimitry Andric }
50230b57cec5SDimitry Andric
50240b57cec5SDimitry Andric switch (Inst.getOpcode()) {
50250b57cec5SDimitry Andric default:
50260b57cec5SDimitry Andric llvm_unreachable("unexpected instruction opcode");
50270b57cec5SDimitry Andric case Mips::ROLImm:
50280b57cec5SDimitry Andric FirstShift = Mips::SLL;
50290b57cec5SDimitry Andric SecondShift = Mips::SRL;
50300b57cec5SDimitry Andric break;
50310b57cec5SDimitry Andric case Mips::RORImm:
50320b57cec5SDimitry Andric FirstShift = Mips::SRL;
50330b57cec5SDimitry Andric SecondShift = Mips::SLL;
50340b57cec5SDimitry Andric break;
50350b57cec5SDimitry Andric }
50360b57cec5SDimitry Andric
50370b57cec5SDimitry Andric ATReg = getATReg(Inst.getLoc());
50380b57cec5SDimitry Andric if (!ATReg)
50390b57cec5SDimitry Andric return true;
50400b57cec5SDimitry Andric
50410b57cec5SDimitry Andric TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), STI);
50420b57cec5SDimitry Andric TOut.emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), STI);
50430b57cec5SDimitry Andric TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
50440b57cec5SDimitry Andric
50450b57cec5SDimitry Andric return false;
50460b57cec5SDimitry Andric }
50470b57cec5SDimitry Andric
50480b57cec5SDimitry Andric return true;
50490b57cec5SDimitry Andric }
50500b57cec5SDimitry Andric
expandDRotation(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)50510b57cec5SDimitry Andric bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
50520b57cec5SDimitry Andric const MCSubtargetInfo *STI) {
50530b57cec5SDimitry Andric MipsTargetStreamer &TOut = getTargetStreamer();
50540b57cec5SDimitry Andric unsigned ATReg = Mips::NoRegister;
50550b57cec5SDimitry Andric unsigned DReg = Inst.getOperand(0).getReg();
50560b57cec5SDimitry Andric unsigned SReg = Inst.getOperand(1).getReg();
50570b57cec5SDimitry Andric unsigned TReg = Inst.getOperand(2).getReg();
50580b57cec5SDimitry Andric unsigned TmpReg = DReg;
50590b57cec5SDimitry Andric
50600b57cec5SDimitry Andric unsigned FirstShift = Mips::NOP;
50610b57cec5SDimitry Andric unsigned SecondShift = Mips::NOP;
50620b57cec5SDimitry Andric
50630b57cec5SDimitry Andric if (hasMips64r2()) {
50640b57cec5SDimitry Andric if (TmpReg == SReg) {
50650b57cec5SDimitry Andric TmpReg = getATReg(Inst.getLoc());
50660b57cec5SDimitry Andric if (!TmpReg)
50670b57cec5SDimitry Andric return true;
50680b57cec5SDimitry Andric }
50690b57cec5SDimitry Andric
50700b57cec5SDimitry Andric if (Inst.getOpcode() == Mips::DROL) {
50710b57cec5SDimitry Andric TOut.emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
50720b57cec5SDimitry Andric TOut.emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
50730b57cec5SDimitry Andric return false;
50740b57cec5SDimitry Andric }
50750b57cec5SDimitry Andric
50760b57cec5SDimitry Andric if (Inst.getOpcode() == Mips::DROR) {
50770b57cec5SDimitry Andric TOut.emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
50780b57cec5SDimitry Andric return false;
50790b57cec5SDimitry Andric }
50800b57cec5SDimitry Andric
50810b57cec5SDimitry Andric return true;
50820b57cec5SDimitry Andric }
50830b57cec5SDimitry Andric
50840b57cec5SDimitry Andric if (hasMips64()) {
50850b57cec5SDimitry Andric switch (Inst.getOpcode()) {
50860b57cec5SDimitry Andric default:
50870b57cec5SDimitry Andric llvm_unreachable("unexpected instruction opcode");
50880b57cec5SDimitry Andric case Mips::DROL:
50890b57cec5SDimitry Andric FirstShift = Mips::DSRLV;
50900b57cec5SDimitry Andric SecondShift = Mips::DSLLV;
50910b57cec5SDimitry Andric break;
50920b57cec5SDimitry Andric case Mips::DROR:
50930b57cec5SDimitry Andric FirstShift = Mips::DSLLV;
50940b57cec5SDimitry Andric SecondShift = Mips::DSRLV;
50950b57cec5SDimitry Andric break;
50960b57cec5SDimitry Andric }
50970b57cec5SDimitry Andric
50980b57cec5SDimitry Andric ATReg = getATReg(Inst.getLoc());
50990b57cec5SDimitry Andric if (!ATReg)
51000b57cec5SDimitry Andric return true;
51010b57cec5SDimitry Andric
51020b57cec5SDimitry Andric TOut.emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
51030b57cec5SDimitry Andric TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
51040b57cec5SDimitry Andric TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
51050b57cec5SDimitry Andric TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
51060b57cec5SDimitry Andric
51070b57cec5SDimitry Andric return false;
51080b57cec5SDimitry Andric }
51090b57cec5SDimitry Andric
51100b57cec5SDimitry Andric return true;
51110b57cec5SDimitry Andric }
51120b57cec5SDimitry Andric
expandDRotationImm(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)51130b57cec5SDimitry Andric bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
51140b57cec5SDimitry Andric MCStreamer &Out,
51150b57cec5SDimitry Andric const MCSubtargetInfo *STI) {
51160b57cec5SDimitry Andric MipsTargetStreamer &TOut = getTargetStreamer();
51170b57cec5SDimitry Andric unsigned ATReg = Mips::NoRegister;
51180b57cec5SDimitry Andric unsigned DReg = Inst.getOperand(0).getReg();
51190b57cec5SDimitry Andric unsigned SReg = Inst.getOperand(1).getReg();
51200b57cec5SDimitry Andric int64_t ImmValue = Inst.getOperand(2).getImm() % 64;
51210b57cec5SDimitry Andric
51220b57cec5SDimitry Andric unsigned FirstShift = Mips::NOP;
51230b57cec5SDimitry Andric unsigned SecondShift = Mips::NOP;
51240b57cec5SDimitry Andric
51250b57cec5SDimitry Andric MCInst TmpInst;
51260b57cec5SDimitry Andric
51270b57cec5SDimitry Andric if (hasMips64r2()) {
51280b57cec5SDimitry Andric unsigned FinalOpcode = Mips::NOP;
51290b57cec5SDimitry Andric if (ImmValue == 0)
51300b57cec5SDimitry Andric FinalOpcode = Mips::DROTR;
51310b57cec5SDimitry Andric else if (ImmValue % 32 == 0)
51320b57cec5SDimitry Andric FinalOpcode = Mips::DROTR32;
51330b57cec5SDimitry Andric else if ((ImmValue >= 1) && (ImmValue <= 32)) {
51340b57cec5SDimitry Andric if (Inst.getOpcode() == Mips::DROLImm)
51350b57cec5SDimitry Andric FinalOpcode = Mips::DROTR32;
51360b57cec5SDimitry Andric else
51370b57cec5SDimitry Andric FinalOpcode = Mips::DROTR;
51380b57cec5SDimitry Andric } else if (ImmValue >= 33) {
51390b57cec5SDimitry Andric if (Inst.getOpcode() == Mips::DROLImm)
51400b57cec5SDimitry Andric FinalOpcode = Mips::DROTR;
51410b57cec5SDimitry Andric else
51420b57cec5SDimitry Andric FinalOpcode = Mips::DROTR32;
51430b57cec5SDimitry Andric }
51440b57cec5SDimitry Andric
51450b57cec5SDimitry Andric uint64_t ShiftValue = ImmValue % 32;
51460b57cec5SDimitry Andric if (Inst.getOpcode() == Mips::DROLImm)
51470b57cec5SDimitry Andric ShiftValue = (32 - ImmValue % 32) % 32;
51480b57cec5SDimitry Andric
51490b57cec5SDimitry Andric TOut.emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
51500b57cec5SDimitry Andric
51510b57cec5SDimitry Andric return false;
51520b57cec5SDimitry Andric }
51530b57cec5SDimitry Andric
51540b57cec5SDimitry Andric if (hasMips64()) {
51550b57cec5SDimitry Andric if (ImmValue == 0) {
51560b57cec5SDimitry Andric TOut.emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), STI);
51570b57cec5SDimitry Andric return false;
51580b57cec5SDimitry Andric }
51590b57cec5SDimitry Andric
51600b57cec5SDimitry Andric switch (Inst.getOpcode()) {
51610b57cec5SDimitry Andric default:
51620b57cec5SDimitry Andric llvm_unreachable("unexpected instruction opcode");
51630b57cec5SDimitry Andric case Mips::DROLImm:
51640b57cec5SDimitry Andric if ((ImmValue >= 1) && (ImmValue <= 31)) {
51650b57cec5SDimitry Andric FirstShift = Mips::DSLL;
51660b57cec5SDimitry Andric SecondShift = Mips::DSRL32;
51670b57cec5SDimitry Andric }
51680b57cec5SDimitry Andric if (ImmValue == 32) {
51690b57cec5SDimitry Andric FirstShift = Mips::DSLL32;
51700b57cec5SDimitry Andric SecondShift = Mips::DSRL32;
51710b57cec5SDimitry Andric }
51720b57cec5SDimitry Andric if ((ImmValue >= 33) && (ImmValue <= 63)) {
51730b57cec5SDimitry Andric FirstShift = Mips::DSLL32;
51740b57cec5SDimitry Andric SecondShift = Mips::DSRL;
51750b57cec5SDimitry Andric }
51760b57cec5SDimitry Andric break;
51770b57cec5SDimitry Andric case Mips::DRORImm:
51780b57cec5SDimitry Andric if ((ImmValue >= 1) && (ImmValue <= 31)) {
51790b57cec5SDimitry Andric FirstShift = Mips::DSRL;
51800b57cec5SDimitry Andric SecondShift = Mips::DSLL32;
51810b57cec5SDimitry Andric }
51820b57cec5SDimitry Andric if (ImmValue == 32) {
51830b57cec5SDimitry Andric FirstShift = Mips::DSRL32;
51840b57cec5SDimitry Andric SecondShift = Mips::DSLL32;
51850b57cec5SDimitry Andric }
51860b57cec5SDimitry Andric if ((ImmValue >= 33) && (ImmValue <= 63)) {
51870b57cec5SDimitry Andric FirstShift = Mips::DSRL32;
51880b57cec5SDimitry Andric SecondShift = Mips::DSLL;
51890b57cec5SDimitry Andric }
51900b57cec5SDimitry Andric break;
51910b57cec5SDimitry Andric }
51920b57cec5SDimitry Andric
51930b57cec5SDimitry Andric ATReg = getATReg(Inst.getLoc());
51940b57cec5SDimitry Andric if (!ATReg)
51950b57cec5SDimitry Andric return true;
51960b57cec5SDimitry Andric
51970b57cec5SDimitry Andric TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), STI);
51980b57cec5SDimitry Andric TOut.emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32,
51990b57cec5SDimitry Andric Inst.getLoc(), STI);
52000b57cec5SDimitry Andric TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
52010b57cec5SDimitry Andric
52020b57cec5SDimitry Andric return false;
52030b57cec5SDimitry Andric }
52040b57cec5SDimitry Andric
52050b57cec5SDimitry Andric return true;
52060b57cec5SDimitry Andric }
52070b57cec5SDimitry Andric
expandAbs(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)52080b57cec5SDimitry Andric bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
52090b57cec5SDimitry Andric const MCSubtargetInfo *STI) {
52100b57cec5SDimitry Andric MipsTargetStreamer &TOut = getTargetStreamer();
52110b57cec5SDimitry Andric unsigned FirstRegOp = Inst.getOperand(0).getReg();
52120b57cec5SDimitry Andric unsigned SecondRegOp = Inst.getOperand(1).getReg();
52130b57cec5SDimitry Andric
52140b57cec5SDimitry Andric TOut.emitRI(Mips::BGEZ, SecondRegOp, 8, IDLoc, STI);
52150b57cec5SDimitry Andric if (FirstRegOp != SecondRegOp)
52160b57cec5SDimitry Andric TOut.emitRRR(Mips::ADDu, FirstRegOp, SecondRegOp, Mips::ZERO, IDLoc, STI);
52170b57cec5SDimitry Andric else
52180b57cec5SDimitry Andric TOut.emitEmptyDelaySlot(false, IDLoc, STI);
52190b57cec5SDimitry Andric TOut.emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, STI);
52200b57cec5SDimitry Andric
52210b57cec5SDimitry Andric return false;
52220b57cec5SDimitry Andric }
52230b57cec5SDimitry Andric
expandMulImm(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)52240b57cec5SDimitry Andric bool MipsAsmParser::expandMulImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
52250b57cec5SDimitry Andric const MCSubtargetInfo *STI) {
52260b57cec5SDimitry Andric MipsTargetStreamer &TOut = getTargetStreamer();
52270b57cec5SDimitry Andric unsigned ATReg = Mips::NoRegister;
52280b57cec5SDimitry Andric unsigned DstReg = Inst.getOperand(0).getReg();
52290b57cec5SDimitry Andric unsigned SrcReg = Inst.getOperand(1).getReg();
52300b57cec5SDimitry Andric int32_t ImmValue = Inst.getOperand(2).getImm();
52310b57cec5SDimitry Andric
52320b57cec5SDimitry Andric ATReg = getATReg(IDLoc);
52330b57cec5SDimitry Andric if (!ATReg)
52340b57cec5SDimitry Andric return true;
52350b57cec5SDimitry Andric
52360b57cec5SDimitry Andric loadImmediate(ImmValue, ATReg, Mips::NoRegister, true, false, IDLoc, Out,
52370b57cec5SDimitry Andric STI);
52380b57cec5SDimitry Andric
52390b57cec5SDimitry Andric TOut.emitRR(Inst.getOpcode() == Mips::MULImmMacro ? Mips::MULT : Mips::DMULT,
52400b57cec5SDimitry Andric SrcReg, ATReg, IDLoc, STI);
52410b57cec5SDimitry Andric
52420b57cec5SDimitry Andric TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
52430b57cec5SDimitry Andric
52440b57cec5SDimitry Andric return false;
52450b57cec5SDimitry Andric }
52460b57cec5SDimitry Andric
expandMulO(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)52470b57cec5SDimitry Andric bool MipsAsmParser::expandMulO(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
52480b57cec5SDimitry Andric const MCSubtargetInfo *STI) {
52490b57cec5SDimitry Andric MipsTargetStreamer &TOut = getTargetStreamer();
52500b57cec5SDimitry Andric unsigned ATReg = Mips::NoRegister;
52510b57cec5SDimitry Andric unsigned DstReg = Inst.getOperand(0).getReg();
52520b57cec5SDimitry Andric unsigned SrcReg = Inst.getOperand(1).getReg();
52530b57cec5SDimitry Andric unsigned TmpReg = Inst.getOperand(2).getReg();
52540b57cec5SDimitry Andric
52550b57cec5SDimitry Andric ATReg = getATReg(Inst.getLoc());
52560b57cec5SDimitry Andric if (!ATReg)
52570b57cec5SDimitry Andric return true;
52580b57cec5SDimitry Andric
52590b57cec5SDimitry Andric TOut.emitRR(Inst.getOpcode() == Mips::MULOMacro ? Mips::MULT : Mips::DMULT,
52600b57cec5SDimitry Andric SrcReg, TmpReg, IDLoc, STI);
52610b57cec5SDimitry Andric
52620b57cec5SDimitry Andric TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
52630b57cec5SDimitry Andric
52640b57cec5SDimitry Andric TOut.emitRRI(Inst.getOpcode() == Mips::MULOMacro ? Mips::SRA : Mips::DSRA32,
52650b57cec5SDimitry Andric DstReg, DstReg, 0x1F, IDLoc, STI);
52660b57cec5SDimitry Andric
52670b57cec5SDimitry Andric TOut.emitR(Mips::MFHI, ATReg, IDLoc, STI);
52680b57cec5SDimitry Andric
52690b57cec5SDimitry Andric if (useTraps()) {
52700b57cec5SDimitry Andric TOut.emitRRI(Mips::TNE, DstReg, ATReg, 6, IDLoc, STI);
52710b57cec5SDimitry Andric } else {
52720b57cec5SDimitry Andric MCContext & Context = TOut.getStreamer().getContext();
52730b57cec5SDimitry Andric MCSymbol * BrTarget = Context.createTempSymbol();
52740b57cec5SDimitry Andric MCOperand LabelOp =
52750b57cec5SDimitry Andric MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
52760b57cec5SDimitry Andric
52770b57cec5SDimitry Andric TOut.emitRRX(Mips::BEQ, DstReg, ATReg, LabelOp, IDLoc, STI);
52780b57cec5SDimitry Andric if (AssemblerOptions.back()->isReorder())
52790b57cec5SDimitry Andric TOut.emitNop(IDLoc, STI);
52800b57cec5SDimitry Andric TOut.emitII(Mips::BREAK, 6, 0, IDLoc, STI);
52810b57cec5SDimitry Andric
52825ffd83dbSDimitry Andric TOut.getStreamer().emitLabel(BrTarget);
52830b57cec5SDimitry Andric }
52840b57cec5SDimitry Andric TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
52850b57cec5SDimitry Andric
52860b57cec5SDimitry Andric return false;
52870b57cec5SDimitry Andric }
52880b57cec5SDimitry Andric
expandMulOU(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)52890b57cec5SDimitry Andric bool MipsAsmParser::expandMulOU(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
52900b57cec5SDimitry Andric const MCSubtargetInfo *STI) {
52910b57cec5SDimitry Andric MipsTargetStreamer &TOut = getTargetStreamer();
52920b57cec5SDimitry Andric unsigned ATReg = Mips::NoRegister;
52930b57cec5SDimitry Andric unsigned DstReg = Inst.getOperand(0).getReg();
52940b57cec5SDimitry Andric unsigned SrcReg = Inst.getOperand(1).getReg();
52950b57cec5SDimitry Andric unsigned TmpReg = Inst.getOperand(2).getReg();
52960b57cec5SDimitry Andric
52970b57cec5SDimitry Andric ATReg = getATReg(IDLoc);
52980b57cec5SDimitry Andric if (!ATReg)
52990b57cec5SDimitry Andric return true;
53000b57cec5SDimitry Andric
53010b57cec5SDimitry Andric TOut.emitRR(Inst.getOpcode() == Mips::MULOUMacro ? Mips::MULTu : Mips::DMULTu,
53020b57cec5SDimitry Andric SrcReg, TmpReg, IDLoc, STI);
53030b57cec5SDimitry Andric
53040b57cec5SDimitry Andric TOut.emitR(Mips::MFHI, ATReg, IDLoc, STI);
53050b57cec5SDimitry Andric TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
53060b57cec5SDimitry Andric if (useTraps()) {
53070b57cec5SDimitry Andric TOut.emitRRI(Mips::TNE, ATReg, Mips::ZERO, 6, IDLoc, STI);
53080b57cec5SDimitry Andric } else {
53090b57cec5SDimitry Andric MCContext & Context = TOut.getStreamer().getContext();
53100b57cec5SDimitry Andric MCSymbol * BrTarget = Context.createTempSymbol();
53110b57cec5SDimitry Andric MCOperand LabelOp =
53120b57cec5SDimitry Andric MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
53130b57cec5SDimitry Andric
53140b57cec5SDimitry Andric TOut.emitRRX(Mips::BEQ, ATReg, Mips::ZERO, LabelOp, IDLoc, STI);
53150b57cec5SDimitry Andric if (AssemblerOptions.back()->isReorder())
53160b57cec5SDimitry Andric TOut.emitNop(IDLoc, STI);
53170b57cec5SDimitry Andric TOut.emitII(Mips::BREAK, 6, 0, IDLoc, STI);
53180b57cec5SDimitry Andric
53195ffd83dbSDimitry Andric TOut.getStreamer().emitLabel(BrTarget);
53200b57cec5SDimitry Andric }
53210b57cec5SDimitry Andric
53220b57cec5SDimitry Andric return false;
53230b57cec5SDimitry Andric }
53240b57cec5SDimitry Andric
expandDMULMacro(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)53250b57cec5SDimitry Andric bool MipsAsmParser::expandDMULMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
53260b57cec5SDimitry Andric const MCSubtargetInfo *STI) {
53270b57cec5SDimitry Andric MipsTargetStreamer &TOut = getTargetStreamer();
53280b57cec5SDimitry Andric unsigned DstReg = Inst.getOperand(0).getReg();
53290b57cec5SDimitry Andric unsigned SrcReg = Inst.getOperand(1).getReg();
53300b57cec5SDimitry Andric unsigned TmpReg = Inst.getOperand(2).getReg();
53310b57cec5SDimitry Andric
53320b57cec5SDimitry Andric TOut.emitRR(Mips::DMULTu, SrcReg, TmpReg, IDLoc, STI);
53330b57cec5SDimitry Andric TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
53340b57cec5SDimitry Andric
53350b57cec5SDimitry Andric return false;
53360b57cec5SDimitry Andric }
53370b57cec5SDimitry Andric
53380b57cec5SDimitry Andric // Expand 'ld $<reg> offset($reg2)' to 'lw $<reg>, offset($reg2);
53390b57cec5SDimitry Andric // lw $<reg+1>>, offset+4($reg2)'
53400b57cec5SDimitry Andric // or expand 'sd $<reg> offset($reg2)' to 'sw $<reg>, offset($reg2);
53410b57cec5SDimitry Andric // sw $<reg+1>>, offset+4($reg2)'
53420b57cec5SDimitry Andric // for O32.
expandLoadStoreDMacro(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI,bool IsLoad)53430b57cec5SDimitry Andric bool MipsAsmParser::expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc,
53440b57cec5SDimitry Andric MCStreamer &Out,
53450b57cec5SDimitry Andric const MCSubtargetInfo *STI,
53460b57cec5SDimitry Andric bool IsLoad) {
53470b57cec5SDimitry Andric if (!isABI_O32())
53480b57cec5SDimitry Andric return true;
53490b57cec5SDimitry Andric
53500b57cec5SDimitry Andric warnIfNoMacro(IDLoc);
53510b57cec5SDimitry Andric
53520b57cec5SDimitry Andric MipsTargetStreamer &TOut = getTargetStreamer();
53530b57cec5SDimitry Andric unsigned Opcode = IsLoad ? Mips::LW : Mips::SW;
53540b57cec5SDimitry Andric unsigned FirstReg = Inst.getOperand(0).getReg();
53550b57cec5SDimitry Andric unsigned SecondReg = nextReg(FirstReg);
53560b57cec5SDimitry Andric unsigned BaseReg = Inst.getOperand(1).getReg();
53570b57cec5SDimitry Andric if (!SecondReg)
53580b57cec5SDimitry Andric return true;
53590b57cec5SDimitry Andric
53600b57cec5SDimitry Andric warnIfRegIndexIsAT(FirstReg, IDLoc);
53610b57cec5SDimitry Andric
53620b57cec5SDimitry Andric assert(Inst.getOperand(2).isImm() &&
53630b57cec5SDimitry Andric "Offset for load macro is not immediate!");
53640b57cec5SDimitry Andric
53650b57cec5SDimitry Andric MCOperand &FirstOffset = Inst.getOperand(2);
53660b57cec5SDimitry Andric signed NextOffset = FirstOffset.getImm() + 4;
53670b57cec5SDimitry Andric MCOperand SecondOffset = MCOperand::createImm(NextOffset);
53680b57cec5SDimitry Andric
53690b57cec5SDimitry Andric if (!isInt<16>(FirstOffset.getImm()) || !isInt<16>(NextOffset))
53700b57cec5SDimitry Andric return true;
53710b57cec5SDimitry Andric
53720b57cec5SDimitry Andric // For loads, clobber the base register with the second load instead of the
53730b57cec5SDimitry Andric // first if the BaseReg == FirstReg.
53740b57cec5SDimitry Andric if (FirstReg != BaseReg || !IsLoad) {
53750b57cec5SDimitry Andric TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
53760b57cec5SDimitry Andric TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
53770b57cec5SDimitry Andric } else {
53780b57cec5SDimitry Andric TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
53790b57cec5SDimitry Andric TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
53800b57cec5SDimitry Andric }
53810b57cec5SDimitry Andric
53820b57cec5SDimitry Andric return false;
53830b57cec5SDimitry Andric }
53840b57cec5SDimitry Andric
53850b57cec5SDimitry Andric
53860b57cec5SDimitry Andric // Expand 's.d $<reg> offset($reg2)' to 'swc1 $<reg+1>, offset($reg2);
53870b57cec5SDimitry Andric // swc1 $<reg>, offset+4($reg2)'
53880b57cec5SDimitry Andric // or if little endian to 'swc1 $<reg>, offset($reg2);
53890b57cec5SDimitry Andric // swc1 $<reg+1>, offset+4($reg2)'
53900b57cec5SDimitry Andric // for Mips1.
expandStoreDM1Macro(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)53910b57cec5SDimitry Andric bool MipsAsmParser::expandStoreDM1Macro(MCInst &Inst, SMLoc IDLoc,
53920b57cec5SDimitry Andric MCStreamer &Out,
53930b57cec5SDimitry Andric const MCSubtargetInfo *STI) {
53940b57cec5SDimitry Andric if (!isABI_O32())
53950b57cec5SDimitry Andric return true;
53960b57cec5SDimitry Andric
53970b57cec5SDimitry Andric warnIfNoMacro(IDLoc);
53980b57cec5SDimitry Andric
53990b57cec5SDimitry Andric MipsTargetStreamer &TOut = getTargetStreamer();
54000b57cec5SDimitry Andric unsigned Opcode = Mips::SWC1;
54010b57cec5SDimitry Andric unsigned FirstReg = Inst.getOperand(0).getReg();
54020b57cec5SDimitry Andric unsigned SecondReg = nextReg(FirstReg);
54030b57cec5SDimitry Andric unsigned BaseReg = Inst.getOperand(1).getReg();
54040b57cec5SDimitry Andric if (!SecondReg)
54050b57cec5SDimitry Andric return true;
54060b57cec5SDimitry Andric
54070b57cec5SDimitry Andric warnIfRegIndexIsAT(FirstReg, IDLoc);
54080b57cec5SDimitry Andric
54090b57cec5SDimitry Andric assert(Inst.getOperand(2).isImm() &&
54100b57cec5SDimitry Andric "Offset for macro is not immediate!");
54110b57cec5SDimitry Andric
54120b57cec5SDimitry Andric MCOperand &FirstOffset = Inst.getOperand(2);
54130b57cec5SDimitry Andric signed NextOffset = FirstOffset.getImm() + 4;
54140b57cec5SDimitry Andric MCOperand SecondOffset = MCOperand::createImm(NextOffset);
54150b57cec5SDimitry Andric
54160b57cec5SDimitry Andric if (!isInt<16>(FirstOffset.getImm()) || !isInt<16>(NextOffset))
54170b57cec5SDimitry Andric return true;
54180b57cec5SDimitry Andric
54190b57cec5SDimitry Andric if (!IsLittleEndian)
54200b57cec5SDimitry Andric std::swap(FirstReg, SecondReg);
54210b57cec5SDimitry Andric
54220b57cec5SDimitry Andric TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
54230b57cec5SDimitry Andric TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
54240b57cec5SDimitry Andric
54250b57cec5SDimitry Andric return false;
54260b57cec5SDimitry Andric }
54270b57cec5SDimitry Andric
expandSeq(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)54280b57cec5SDimitry Andric bool MipsAsmParser::expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
54290b57cec5SDimitry Andric const MCSubtargetInfo *STI) {
54300b57cec5SDimitry Andric MipsTargetStreamer &TOut = getTargetStreamer();
54310b57cec5SDimitry Andric
54320b57cec5SDimitry Andric assert(Inst.getNumOperands() == 3 && "Invalid operand count");
54330b57cec5SDimitry Andric assert(Inst.getOperand(0).isReg() &&
54340b57cec5SDimitry Andric Inst.getOperand(1).isReg() &&
54350b57cec5SDimitry Andric Inst.getOperand(2).isReg() && "Invalid instruction operand.");
54360b57cec5SDimitry Andric
54370b57cec5SDimitry Andric unsigned DstReg = Inst.getOperand(0).getReg();
54380b57cec5SDimitry Andric unsigned SrcReg = Inst.getOperand(1).getReg();
54390b57cec5SDimitry Andric unsigned OpReg = Inst.getOperand(2).getReg();
54400b57cec5SDimitry Andric
54410b57cec5SDimitry Andric warnIfNoMacro(IDLoc);
54420b57cec5SDimitry Andric
54430b57cec5SDimitry Andric if (SrcReg != Mips::ZERO && OpReg != Mips::ZERO) {
54440b57cec5SDimitry Andric TOut.emitRRR(Mips::XOR, DstReg, SrcReg, OpReg, IDLoc, STI);
54450b57cec5SDimitry Andric TOut.emitRRI(Mips::SLTiu, DstReg, DstReg, 1, IDLoc, STI);
54460b57cec5SDimitry Andric return false;
54470b57cec5SDimitry Andric }
54480b57cec5SDimitry Andric
54490b57cec5SDimitry Andric unsigned Reg = SrcReg == Mips::ZERO ? OpReg : SrcReg;
54500b57cec5SDimitry Andric TOut.emitRRI(Mips::SLTiu, DstReg, Reg, 1, IDLoc, STI);
54510b57cec5SDimitry Andric return false;
54520b57cec5SDimitry Andric }
54530b57cec5SDimitry Andric
expandSeqI(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)54540b57cec5SDimitry Andric bool MipsAsmParser::expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
54550b57cec5SDimitry Andric const MCSubtargetInfo *STI) {
54560b57cec5SDimitry Andric MipsTargetStreamer &TOut = getTargetStreamer();
54570b57cec5SDimitry Andric
54580b57cec5SDimitry Andric assert(Inst.getNumOperands() == 3 && "Invalid operand count");
54590b57cec5SDimitry Andric assert(Inst.getOperand(0).isReg() &&
54600b57cec5SDimitry Andric Inst.getOperand(1).isReg() &&
54610b57cec5SDimitry Andric Inst.getOperand(2).isImm() && "Invalid instruction operand.");
54620b57cec5SDimitry Andric
54630b57cec5SDimitry Andric unsigned DstReg = Inst.getOperand(0).getReg();
54640b57cec5SDimitry Andric unsigned SrcReg = Inst.getOperand(1).getReg();
54650b57cec5SDimitry Andric int64_t Imm = Inst.getOperand(2).getImm();
54660b57cec5SDimitry Andric
54670b57cec5SDimitry Andric warnIfNoMacro(IDLoc);
54680b57cec5SDimitry Andric
54690b57cec5SDimitry Andric if (Imm == 0) {
54700b57cec5SDimitry Andric TOut.emitRRI(Mips::SLTiu, DstReg, SrcReg, 1, IDLoc, STI);
54710b57cec5SDimitry Andric return false;
54720b57cec5SDimitry Andric }
54730b57cec5SDimitry Andric
54740b57cec5SDimitry Andric if (SrcReg == Mips::ZERO) {
54750b57cec5SDimitry Andric Warning(IDLoc, "comparison is always false");
54760b57cec5SDimitry Andric TOut.emitRRR(isGP64bit() ? Mips::DADDu : Mips::ADDu,
54770b57cec5SDimitry Andric DstReg, SrcReg, SrcReg, IDLoc, STI);
54780b57cec5SDimitry Andric return false;
54790b57cec5SDimitry Andric }
54800b57cec5SDimitry Andric
54810b57cec5SDimitry Andric unsigned Opc;
54820b57cec5SDimitry Andric if (Imm > -0x8000 && Imm < 0) {
54830b57cec5SDimitry Andric Imm = -Imm;
54840b57cec5SDimitry Andric Opc = isGP64bit() ? Mips::DADDiu : Mips::ADDiu;
54850b57cec5SDimitry Andric } else {
54860b57cec5SDimitry Andric Opc = Mips::XORi;
54870b57cec5SDimitry Andric }
54880b57cec5SDimitry Andric
54890b57cec5SDimitry Andric if (!isUInt<16>(Imm)) {
54900b57cec5SDimitry Andric unsigned ATReg = getATReg(IDLoc);
54910b57cec5SDimitry Andric if (!ATReg)
54920b57cec5SDimitry Andric return true;
54930b57cec5SDimitry Andric
54940b57cec5SDimitry Andric if (loadImmediate(Imm, ATReg, Mips::NoRegister, true, isGP64bit(), IDLoc,
54950b57cec5SDimitry Andric Out, STI))
54960b57cec5SDimitry Andric return true;
54970b57cec5SDimitry Andric
54980b57cec5SDimitry Andric TOut.emitRRR(Mips::XOR, DstReg, SrcReg, ATReg, IDLoc, STI);
54990b57cec5SDimitry Andric TOut.emitRRI(Mips::SLTiu, DstReg, DstReg, 1, IDLoc, STI);
55000b57cec5SDimitry Andric return false;
55010b57cec5SDimitry Andric }
55020b57cec5SDimitry Andric
55030b57cec5SDimitry Andric TOut.emitRRI(Opc, DstReg, SrcReg, Imm, IDLoc, STI);
55040b57cec5SDimitry Andric TOut.emitRRI(Mips::SLTiu, DstReg, DstReg, 1, IDLoc, STI);
55050b57cec5SDimitry Andric return false;
55060b57cec5SDimitry Andric }
55070b57cec5SDimitry Andric
expandSne(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)55085ffd83dbSDimitry Andric bool MipsAsmParser::expandSne(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
55095ffd83dbSDimitry Andric const MCSubtargetInfo *STI) {
55105ffd83dbSDimitry Andric
55115ffd83dbSDimitry Andric MipsTargetStreamer &TOut = getTargetStreamer();
55125ffd83dbSDimitry Andric
55135ffd83dbSDimitry Andric assert(Inst.getNumOperands() == 3 && "Invalid operand count");
55145ffd83dbSDimitry Andric assert(Inst.getOperand(0).isReg() &&
55155ffd83dbSDimitry Andric Inst.getOperand(1).isReg() &&
55165ffd83dbSDimitry Andric Inst.getOperand(2).isReg() && "Invalid instruction operand.");
55175ffd83dbSDimitry Andric
55185ffd83dbSDimitry Andric unsigned DstReg = Inst.getOperand(0).getReg();
55195ffd83dbSDimitry Andric unsigned SrcReg = Inst.getOperand(1).getReg();
55205ffd83dbSDimitry Andric unsigned OpReg = Inst.getOperand(2).getReg();
55215ffd83dbSDimitry Andric
55225ffd83dbSDimitry Andric warnIfNoMacro(IDLoc);
55235ffd83dbSDimitry Andric
55245ffd83dbSDimitry Andric if (SrcReg != Mips::ZERO && OpReg != Mips::ZERO) {
55255ffd83dbSDimitry Andric TOut.emitRRR(Mips::XOR, DstReg, SrcReg, OpReg, IDLoc, STI);
55265ffd83dbSDimitry Andric TOut.emitRRR(Mips::SLTu, DstReg, Mips::ZERO, DstReg, IDLoc, STI);
55275ffd83dbSDimitry Andric return false;
55285ffd83dbSDimitry Andric }
55295ffd83dbSDimitry Andric
55305ffd83dbSDimitry Andric unsigned Reg = SrcReg == Mips::ZERO ? OpReg : SrcReg;
55315ffd83dbSDimitry Andric TOut.emitRRR(Mips::SLTu, DstReg, Mips::ZERO, Reg, IDLoc, STI);
55325ffd83dbSDimitry Andric return false;
55335ffd83dbSDimitry Andric }
55345ffd83dbSDimitry Andric
expandSneI(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)55355ffd83dbSDimitry Andric bool MipsAsmParser::expandSneI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
55365ffd83dbSDimitry Andric const MCSubtargetInfo *STI) {
55375ffd83dbSDimitry Andric MipsTargetStreamer &TOut = getTargetStreamer();
55385ffd83dbSDimitry Andric
55395ffd83dbSDimitry Andric assert(Inst.getNumOperands() == 3 && "Invalid operand count");
55405ffd83dbSDimitry Andric assert(Inst.getOperand(0).isReg() &&
55415ffd83dbSDimitry Andric Inst.getOperand(1).isReg() &&
55425ffd83dbSDimitry Andric Inst.getOperand(2).isImm() && "Invalid instruction operand.");
55435ffd83dbSDimitry Andric
55445ffd83dbSDimitry Andric unsigned DstReg = Inst.getOperand(0).getReg();
55455ffd83dbSDimitry Andric unsigned SrcReg = Inst.getOperand(1).getReg();
55465ffd83dbSDimitry Andric int64_t ImmValue = Inst.getOperand(2).getImm();
55475ffd83dbSDimitry Andric
55485ffd83dbSDimitry Andric warnIfNoMacro(IDLoc);
55495ffd83dbSDimitry Andric
55505ffd83dbSDimitry Andric if (ImmValue == 0) {
55515ffd83dbSDimitry Andric TOut.emitRRR(Mips::SLTu, DstReg, Mips::ZERO, SrcReg, IDLoc, STI);
55525ffd83dbSDimitry Andric return false;
55535ffd83dbSDimitry Andric }
55545ffd83dbSDimitry Andric
55555ffd83dbSDimitry Andric if (SrcReg == Mips::ZERO) {
55565ffd83dbSDimitry Andric Warning(IDLoc, "comparison is always true");
55575ffd83dbSDimitry Andric if (loadImmediate(1, DstReg, Mips::NoRegister, true, false, IDLoc, Out,
55585ffd83dbSDimitry Andric STI))
55595ffd83dbSDimitry Andric return true;
55605ffd83dbSDimitry Andric return false;
55615ffd83dbSDimitry Andric }
55625ffd83dbSDimitry Andric
55635ffd83dbSDimitry Andric unsigned Opc;
55645ffd83dbSDimitry Andric if (ImmValue > -0x8000 && ImmValue < 0) {
55655ffd83dbSDimitry Andric ImmValue = -ImmValue;
55665ffd83dbSDimitry Andric Opc = isGP64bit() ? Mips::DADDiu : Mips::ADDiu;
55675ffd83dbSDimitry Andric } else {
55685ffd83dbSDimitry Andric Opc = Mips::XORi;
55695ffd83dbSDimitry Andric }
55705ffd83dbSDimitry Andric
55715ffd83dbSDimitry Andric if (isUInt<16>(ImmValue)) {
55725ffd83dbSDimitry Andric TOut.emitRRI(Opc, DstReg, SrcReg, ImmValue, IDLoc, STI);
55735ffd83dbSDimitry Andric TOut.emitRRR(Mips::SLTu, DstReg, Mips::ZERO, DstReg, IDLoc, STI);
55745ffd83dbSDimitry Andric return false;
55755ffd83dbSDimitry Andric }
55765ffd83dbSDimitry Andric
55775ffd83dbSDimitry Andric unsigned ATReg = getATReg(IDLoc);
55785ffd83dbSDimitry Andric if (!ATReg)
55795ffd83dbSDimitry Andric return true;
55805ffd83dbSDimitry Andric
55815ffd83dbSDimitry Andric if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, isInt<32>(ImmValue),
55825ffd83dbSDimitry Andric false, IDLoc, Out, STI))
55835ffd83dbSDimitry Andric return true;
55845ffd83dbSDimitry Andric
55855ffd83dbSDimitry Andric TOut.emitRRR(Mips::XOR, DstReg, SrcReg, ATReg, IDLoc, STI);
55865ffd83dbSDimitry Andric TOut.emitRRR(Mips::SLTu, DstReg, Mips::ZERO, DstReg, IDLoc, STI);
55875ffd83dbSDimitry Andric return false;
55885ffd83dbSDimitry Andric }
55895ffd83dbSDimitry Andric
55900b57cec5SDimitry Andric // Map the DSP accumulator and control register to the corresponding gpr
55910b57cec5SDimitry Andric // operand. Unlike the other alias, the m(f|t)t(lo|hi|acx) instructions
55920b57cec5SDimitry Andric // do not map the DSP registers contigously to gpr registers.
getRegisterForMxtrDSP(MCInst & Inst,bool IsMFDSP)55930b57cec5SDimitry Andric static unsigned getRegisterForMxtrDSP(MCInst &Inst, bool IsMFDSP) {
55940b57cec5SDimitry Andric switch (Inst.getOpcode()) {
55950b57cec5SDimitry Andric case Mips::MFTLO:
55960b57cec5SDimitry Andric case Mips::MTTLO:
55970b57cec5SDimitry Andric switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg()) {
55980b57cec5SDimitry Andric case Mips::AC0:
55990b57cec5SDimitry Andric return Mips::ZERO;
56000b57cec5SDimitry Andric case Mips::AC1:
56010b57cec5SDimitry Andric return Mips::A0;
56020b57cec5SDimitry Andric case Mips::AC2:
56030b57cec5SDimitry Andric return Mips::T0;
56040b57cec5SDimitry Andric case Mips::AC3:
56050b57cec5SDimitry Andric return Mips::T4;
56060b57cec5SDimitry Andric default:
56070b57cec5SDimitry Andric llvm_unreachable("Unknown register for 'mttr' alias!");
56080b57cec5SDimitry Andric }
56090b57cec5SDimitry Andric case Mips::MFTHI:
56100b57cec5SDimitry Andric case Mips::MTTHI:
56110b57cec5SDimitry Andric switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg()) {
56120b57cec5SDimitry Andric case Mips::AC0:
56130b57cec5SDimitry Andric return Mips::AT;
56140b57cec5SDimitry Andric case Mips::AC1:
56150b57cec5SDimitry Andric return Mips::A1;
56160b57cec5SDimitry Andric case Mips::AC2:
56170b57cec5SDimitry Andric return Mips::T1;
56180b57cec5SDimitry Andric case Mips::AC3:
56190b57cec5SDimitry Andric return Mips::T5;
56200b57cec5SDimitry Andric default:
56210b57cec5SDimitry Andric llvm_unreachable("Unknown register for 'mttr' alias!");
56220b57cec5SDimitry Andric }
56230b57cec5SDimitry Andric case Mips::MFTACX:
56240b57cec5SDimitry Andric case Mips::MTTACX:
56250b57cec5SDimitry Andric switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg()) {
56260b57cec5SDimitry Andric case Mips::AC0:
56270b57cec5SDimitry Andric return Mips::V0;
56280b57cec5SDimitry Andric case Mips::AC1:
56290b57cec5SDimitry Andric return Mips::A2;
56300b57cec5SDimitry Andric case Mips::AC2:
56310b57cec5SDimitry Andric return Mips::T2;
56320b57cec5SDimitry Andric case Mips::AC3:
56330b57cec5SDimitry Andric return Mips::T6;
56340b57cec5SDimitry Andric default:
56350b57cec5SDimitry Andric llvm_unreachable("Unknown register for 'mttr' alias!");
56360b57cec5SDimitry Andric }
56370b57cec5SDimitry Andric case Mips::MFTDSP:
56380b57cec5SDimitry Andric case Mips::MTTDSP:
56390b57cec5SDimitry Andric return Mips::S0;
56400b57cec5SDimitry Andric default:
56410b57cec5SDimitry Andric llvm_unreachable("Unknown instruction for 'mttr' dsp alias!");
56420b57cec5SDimitry Andric }
56430b57cec5SDimitry Andric }
56440b57cec5SDimitry Andric
56450b57cec5SDimitry Andric // Map the floating point register operand to the corresponding register
56460b57cec5SDimitry Andric // operand.
getRegisterForMxtrFP(MCInst & Inst,bool IsMFTC1)56470b57cec5SDimitry Andric static unsigned getRegisterForMxtrFP(MCInst &Inst, bool IsMFTC1) {
56480b57cec5SDimitry Andric switch (Inst.getOperand(IsMFTC1 ? 1 : 0).getReg()) {
56490b57cec5SDimitry Andric case Mips::F0: return Mips::ZERO;
56500b57cec5SDimitry Andric case Mips::F1: return Mips::AT;
56510b57cec5SDimitry Andric case Mips::F2: return Mips::V0;
56520b57cec5SDimitry Andric case Mips::F3: return Mips::V1;
56530b57cec5SDimitry Andric case Mips::F4: return Mips::A0;
56540b57cec5SDimitry Andric case Mips::F5: return Mips::A1;
56550b57cec5SDimitry Andric case Mips::F6: return Mips::A2;
56560b57cec5SDimitry Andric case Mips::F7: return Mips::A3;
56570b57cec5SDimitry Andric case Mips::F8: return Mips::T0;
56580b57cec5SDimitry Andric case Mips::F9: return Mips::T1;
56590b57cec5SDimitry Andric case Mips::F10: return Mips::T2;
56600b57cec5SDimitry Andric case Mips::F11: return Mips::T3;
56610b57cec5SDimitry Andric case Mips::F12: return Mips::T4;
56620b57cec5SDimitry Andric case Mips::F13: return Mips::T5;
56630b57cec5SDimitry Andric case Mips::F14: return Mips::T6;
56640b57cec5SDimitry Andric case Mips::F15: return Mips::T7;
56650b57cec5SDimitry Andric case Mips::F16: return Mips::S0;
56660b57cec5SDimitry Andric case Mips::F17: return Mips::S1;
56670b57cec5SDimitry Andric case Mips::F18: return Mips::S2;
56680b57cec5SDimitry Andric case Mips::F19: return Mips::S3;
56690b57cec5SDimitry Andric case Mips::F20: return Mips::S4;
56700b57cec5SDimitry Andric case Mips::F21: return Mips::S5;
56710b57cec5SDimitry Andric case Mips::F22: return Mips::S6;
56720b57cec5SDimitry Andric case Mips::F23: return Mips::S7;
56730b57cec5SDimitry Andric case Mips::F24: return Mips::T8;
56740b57cec5SDimitry Andric case Mips::F25: return Mips::T9;
56750b57cec5SDimitry Andric case Mips::F26: return Mips::K0;
56760b57cec5SDimitry Andric case Mips::F27: return Mips::K1;
56770b57cec5SDimitry Andric case Mips::F28: return Mips::GP;
56780b57cec5SDimitry Andric case Mips::F29: return Mips::SP;
56790b57cec5SDimitry Andric case Mips::F30: return Mips::FP;
56800b57cec5SDimitry Andric case Mips::F31: return Mips::RA;
56810b57cec5SDimitry Andric default: llvm_unreachable("Unknown register for mttc1 alias!");
56820b57cec5SDimitry Andric }
56830b57cec5SDimitry Andric }
56840b57cec5SDimitry Andric
56850b57cec5SDimitry Andric // Map the coprocessor operand the corresponding gpr register operand.
getRegisterForMxtrC0(MCInst & Inst,bool IsMFTC0)56860b57cec5SDimitry Andric static unsigned getRegisterForMxtrC0(MCInst &Inst, bool IsMFTC0) {
56870b57cec5SDimitry Andric switch (Inst.getOperand(IsMFTC0 ? 1 : 0).getReg()) {
56880b57cec5SDimitry Andric case Mips::COP00: return Mips::ZERO;
56890b57cec5SDimitry Andric case Mips::COP01: return Mips::AT;
56900b57cec5SDimitry Andric case Mips::COP02: return Mips::V0;
56910b57cec5SDimitry Andric case Mips::COP03: return Mips::V1;
56920b57cec5SDimitry Andric case Mips::COP04: return Mips::A0;
56930b57cec5SDimitry Andric case Mips::COP05: return Mips::A1;
56940b57cec5SDimitry Andric case Mips::COP06: return Mips::A2;
56950b57cec5SDimitry Andric case Mips::COP07: return Mips::A3;
56960b57cec5SDimitry Andric case Mips::COP08: return Mips::T0;
56970b57cec5SDimitry Andric case Mips::COP09: return Mips::T1;
56980b57cec5SDimitry Andric case Mips::COP010: return Mips::T2;
56990b57cec5SDimitry Andric case Mips::COP011: return Mips::T3;
57000b57cec5SDimitry Andric case Mips::COP012: return Mips::T4;
57010b57cec5SDimitry Andric case Mips::COP013: return Mips::T5;
57020b57cec5SDimitry Andric case Mips::COP014: return Mips::T6;
57030b57cec5SDimitry Andric case Mips::COP015: return Mips::T7;
57040b57cec5SDimitry Andric case Mips::COP016: return Mips::S0;
57050b57cec5SDimitry Andric case Mips::COP017: return Mips::S1;
57060b57cec5SDimitry Andric case Mips::COP018: return Mips::S2;
57070b57cec5SDimitry Andric case Mips::COP019: return Mips::S3;
57080b57cec5SDimitry Andric case Mips::COP020: return Mips::S4;
57090b57cec5SDimitry Andric case Mips::COP021: return Mips::S5;
57100b57cec5SDimitry Andric case Mips::COP022: return Mips::S6;
57110b57cec5SDimitry Andric case Mips::COP023: return Mips::S7;
57120b57cec5SDimitry Andric case Mips::COP024: return Mips::T8;
57130b57cec5SDimitry Andric case Mips::COP025: return Mips::T9;
57140b57cec5SDimitry Andric case Mips::COP026: return Mips::K0;
57150b57cec5SDimitry Andric case Mips::COP027: return Mips::K1;
57160b57cec5SDimitry Andric case Mips::COP028: return Mips::GP;
57170b57cec5SDimitry Andric case Mips::COP029: return Mips::SP;
57180b57cec5SDimitry Andric case Mips::COP030: return Mips::FP;
57190b57cec5SDimitry Andric case Mips::COP031: return Mips::RA;
57200b57cec5SDimitry Andric default: llvm_unreachable("Unknown register for mttc0 alias!");
57210b57cec5SDimitry Andric }
57220b57cec5SDimitry Andric }
57230b57cec5SDimitry Andric
57240b57cec5SDimitry Andric /// Expand an alias of 'mftr' or 'mttr' into the full instruction, by producing
57250b57cec5SDimitry Andric /// an mftr or mttr with the correctly mapped gpr register, u, sel and h bits.
expandMXTRAlias(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)57260b57cec5SDimitry Andric bool MipsAsmParser::expandMXTRAlias(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
57270b57cec5SDimitry Andric const MCSubtargetInfo *STI) {
57280b57cec5SDimitry Andric MipsTargetStreamer &TOut = getTargetStreamer();
57290b57cec5SDimitry Andric unsigned rd = 0;
57300b57cec5SDimitry Andric unsigned u = 1;
57310b57cec5SDimitry Andric unsigned sel = 0;
57320b57cec5SDimitry Andric unsigned h = 0;
57330b57cec5SDimitry Andric bool IsMFTR = false;
57340b57cec5SDimitry Andric switch (Inst.getOpcode()) {
57350b57cec5SDimitry Andric case Mips::MFTC0:
57360b57cec5SDimitry Andric IsMFTR = true;
5737bdd1243dSDimitry Andric [[fallthrough]];
57380b57cec5SDimitry Andric case Mips::MTTC0:
57390b57cec5SDimitry Andric u = 0;
57400b57cec5SDimitry Andric rd = getRegisterForMxtrC0(Inst, IsMFTR);
57410b57cec5SDimitry Andric sel = Inst.getOperand(2).getImm();
57420b57cec5SDimitry Andric break;
57430b57cec5SDimitry Andric case Mips::MFTGPR:
57440b57cec5SDimitry Andric IsMFTR = true;
5745bdd1243dSDimitry Andric [[fallthrough]];
57460b57cec5SDimitry Andric case Mips::MTTGPR:
57470b57cec5SDimitry Andric rd = Inst.getOperand(IsMFTR ? 1 : 0).getReg();
57480b57cec5SDimitry Andric break;
57490b57cec5SDimitry Andric case Mips::MFTLO:
57500b57cec5SDimitry Andric case Mips::MFTHI:
57510b57cec5SDimitry Andric case Mips::MFTACX:
57520b57cec5SDimitry Andric case Mips::MFTDSP:
57530b57cec5SDimitry Andric IsMFTR = true;
5754bdd1243dSDimitry Andric [[fallthrough]];
57550b57cec5SDimitry Andric case Mips::MTTLO:
57560b57cec5SDimitry Andric case Mips::MTTHI:
57570b57cec5SDimitry Andric case Mips::MTTACX:
57580b57cec5SDimitry Andric case Mips::MTTDSP:
57590b57cec5SDimitry Andric rd = getRegisterForMxtrDSP(Inst, IsMFTR);
57600b57cec5SDimitry Andric sel = 1;
57610b57cec5SDimitry Andric break;
57620b57cec5SDimitry Andric case Mips::MFTHC1:
57630b57cec5SDimitry Andric h = 1;
5764bdd1243dSDimitry Andric [[fallthrough]];
57650b57cec5SDimitry Andric case Mips::MFTC1:
57660b57cec5SDimitry Andric IsMFTR = true;
57670b57cec5SDimitry Andric rd = getRegisterForMxtrFP(Inst, IsMFTR);
57680b57cec5SDimitry Andric sel = 2;
57690b57cec5SDimitry Andric break;
57700b57cec5SDimitry Andric case Mips::MTTHC1:
57710b57cec5SDimitry Andric h = 1;
5772bdd1243dSDimitry Andric [[fallthrough]];
57730b57cec5SDimitry Andric case Mips::MTTC1:
57740b57cec5SDimitry Andric rd = getRegisterForMxtrFP(Inst, IsMFTR);
57750b57cec5SDimitry Andric sel = 2;
57760b57cec5SDimitry Andric break;
57770b57cec5SDimitry Andric case Mips::CFTC1:
57780b57cec5SDimitry Andric IsMFTR = true;
5779bdd1243dSDimitry Andric [[fallthrough]];
57800b57cec5SDimitry Andric case Mips::CTTC1:
57810b57cec5SDimitry Andric rd = getRegisterForMxtrFP(Inst, IsMFTR);
57820b57cec5SDimitry Andric sel = 3;
57830b57cec5SDimitry Andric break;
57840b57cec5SDimitry Andric }
57850b57cec5SDimitry Andric unsigned Op0 = IsMFTR ? Inst.getOperand(0).getReg() : rd;
57860b57cec5SDimitry Andric unsigned Op1 =
57870b57cec5SDimitry Andric IsMFTR ? rd
57880b57cec5SDimitry Andric : (Inst.getOpcode() != Mips::MTTDSP ? Inst.getOperand(1).getReg()
57890b57cec5SDimitry Andric : Inst.getOperand(0).getReg());
57900b57cec5SDimitry Andric
57910b57cec5SDimitry Andric TOut.emitRRIII(IsMFTR ? Mips::MFTR : Mips::MTTR, Op0, Op1, u, sel, h, IDLoc,
57920b57cec5SDimitry Andric STI);
57930b57cec5SDimitry Andric return false;
57940b57cec5SDimitry Andric }
57950b57cec5SDimitry Andric
expandSaaAddr(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)57960b57cec5SDimitry Andric bool MipsAsmParser::expandSaaAddr(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
57970b57cec5SDimitry Andric const MCSubtargetInfo *STI) {
57980b57cec5SDimitry Andric assert(Inst.getNumOperands() == 3 && "expected three operands");
57990b57cec5SDimitry Andric assert(Inst.getOperand(0).isReg() && "expected register operand kind");
58000b57cec5SDimitry Andric assert(Inst.getOperand(1).isReg() && "expected register operand kind");
58010b57cec5SDimitry Andric
58020b57cec5SDimitry Andric warnIfNoMacro(IDLoc);
58030b57cec5SDimitry Andric
58040b57cec5SDimitry Andric MipsTargetStreamer &TOut = getTargetStreamer();
58050b57cec5SDimitry Andric unsigned Opcode = Inst.getOpcode() == Mips::SaaAddr ? Mips::SAA : Mips::SAAD;
58060b57cec5SDimitry Andric unsigned RtReg = Inst.getOperand(0).getReg();
58070b57cec5SDimitry Andric unsigned BaseReg = Inst.getOperand(1).getReg();
58080b57cec5SDimitry Andric const MCOperand &BaseOp = Inst.getOperand(2);
58090b57cec5SDimitry Andric
58100b57cec5SDimitry Andric if (BaseOp.isImm()) {
58110b57cec5SDimitry Andric int64_t ImmValue = BaseOp.getImm();
58120b57cec5SDimitry Andric if (ImmValue == 0) {
58130b57cec5SDimitry Andric TOut.emitRR(Opcode, RtReg, BaseReg, IDLoc, STI);
58140b57cec5SDimitry Andric return false;
58150b57cec5SDimitry Andric }
58160b57cec5SDimitry Andric }
58170b57cec5SDimitry Andric
58180b57cec5SDimitry Andric unsigned ATReg = getATReg(IDLoc);
58190b57cec5SDimitry Andric if (!ATReg)
58200b57cec5SDimitry Andric return true;
58210b57cec5SDimitry Andric
58220b57cec5SDimitry Andric if (expandLoadAddress(ATReg, BaseReg, BaseOp, !isGP64bit(), IDLoc, Out, STI))
58230b57cec5SDimitry Andric return true;
58240b57cec5SDimitry Andric
58250b57cec5SDimitry Andric TOut.emitRR(Opcode, RtReg, ATReg, IDLoc, STI);
58260b57cec5SDimitry Andric return false;
58270b57cec5SDimitry Andric }
58280b57cec5SDimitry Andric
58290b57cec5SDimitry Andric unsigned
checkEarlyTargetMatchPredicate(MCInst & Inst,const OperandVector & Operands)58300b57cec5SDimitry Andric MipsAsmParser::checkEarlyTargetMatchPredicate(MCInst &Inst,
58310b57cec5SDimitry Andric const OperandVector &Operands) {
58320b57cec5SDimitry Andric switch (Inst.getOpcode()) {
58330b57cec5SDimitry Andric default:
58340b57cec5SDimitry Andric return Match_Success;
58350b57cec5SDimitry Andric case Mips::DATI:
58360b57cec5SDimitry Andric case Mips::DAHI:
58370b57cec5SDimitry Andric if (static_cast<MipsOperand &>(*Operands[1])
58380b57cec5SDimitry Andric .isValidForTie(static_cast<MipsOperand &>(*Operands[2])))
58390b57cec5SDimitry Andric return Match_Success;
58400b57cec5SDimitry Andric return Match_RequiresSameSrcAndDst;
58410b57cec5SDimitry Andric }
58420b57cec5SDimitry Andric }
58430b57cec5SDimitry Andric
checkTargetMatchPredicate(MCInst & Inst)58440b57cec5SDimitry Andric unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
58450b57cec5SDimitry Andric switch (Inst.getOpcode()) {
58460b57cec5SDimitry Andric // As described by the MIPSR6 spec, daui must not use the zero operand for
58470b57cec5SDimitry Andric // its source operand.
58480b57cec5SDimitry Andric case Mips::DAUI:
58490b57cec5SDimitry Andric if (Inst.getOperand(1).getReg() == Mips::ZERO ||
58500b57cec5SDimitry Andric Inst.getOperand(1).getReg() == Mips::ZERO_64)
58510b57cec5SDimitry Andric return Match_RequiresNoZeroRegister;
58520b57cec5SDimitry Andric return Match_Success;
58530b57cec5SDimitry Andric // As described by the Mips32r2 spec, the registers Rd and Rs for
58540b57cec5SDimitry Andric // jalr.hb must be different.
58550b57cec5SDimitry Andric // It also applies for registers Rt and Rs of microMIPSr6 jalrc.hb instruction
58560b57cec5SDimitry Andric // and registers Rd and Base for microMIPS lwp instruction
58570b57cec5SDimitry Andric case Mips::JALR_HB:
58580b57cec5SDimitry Andric case Mips::JALR_HB64:
58590b57cec5SDimitry Andric case Mips::JALRC_HB_MMR6:
58600b57cec5SDimitry Andric case Mips::JALRC_MMR6:
58610b57cec5SDimitry Andric if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
58620b57cec5SDimitry Andric return Match_RequiresDifferentSrcAndDst;
58630b57cec5SDimitry Andric return Match_Success;
58640b57cec5SDimitry Andric case Mips::LWP_MM:
58650b57cec5SDimitry Andric if (Inst.getOperand(0).getReg() == Inst.getOperand(2).getReg())
58660b57cec5SDimitry Andric return Match_RequiresDifferentSrcAndDst;
58670b57cec5SDimitry Andric return Match_Success;
58680b57cec5SDimitry Andric case Mips::SYNC:
58690b57cec5SDimitry Andric if (Inst.getOperand(0).getImm() != 0 && !hasMips32())
58700b57cec5SDimitry Andric return Match_NonZeroOperandForSync;
58710b57cec5SDimitry Andric return Match_Success;
58720b57cec5SDimitry Andric case Mips::MFC0:
58730b57cec5SDimitry Andric case Mips::MTC0:
58740b57cec5SDimitry Andric case Mips::MTC2:
58750b57cec5SDimitry Andric case Mips::MFC2:
58760b57cec5SDimitry Andric if (Inst.getOperand(2).getImm() != 0 && !hasMips32())
58770b57cec5SDimitry Andric return Match_NonZeroOperandForMTCX;
58780b57cec5SDimitry Andric return Match_Success;
58790b57cec5SDimitry Andric // As described the MIPSR6 spec, the compact branches that compare registers
58800b57cec5SDimitry Andric // must:
58810b57cec5SDimitry Andric // a) Not use the zero register.
58820b57cec5SDimitry Andric // b) Not use the same register twice.
58830b57cec5SDimitry Andric // c) rs < rt for bnec, beqc.
58840b57cec5SDimitry Andric // NB: For this case, the encoding will swap the operands as their
58850b57cec5SDimitry Andric // ordering doesn't matter. GAS performs this transformation too.
58860b57cec5SDimitry Andric // Hence, that constraint does not have to be enforced.
58870b57cec5SDimitry Andric //
58880b57cec5SDimitry Andric // The compact branches that branch iff the signed addition of two registers
58890b57cec5SDimitry Andric // would overflow must have rs >= rt. That can be handled like beqc/bnec with
58900b57cec5SDimitry Andric // operand swapping. They do not have restriction of using the zero register.
58910b57cec5SDimitry Andric case Mips::BLEZC: case Mips::BLEZC_MMR6:
58920b57cec5SDimitry Andric case Mips::BGEZC: case Mips::BGEZC_MMR6:
58930b57cec5SDimitry Andric case Mips::BGTZC: case Mips::BGTZC_MMR6:
58940b57cec5SDimitry Andric case Mips::BLTZC: case Mips::BLTZC_MMR6:
58950b57cec5SDimitry Andric case Mips::BEQZC: case Mips::BEQZC_MMR6:
58960b57cec5SDimitry Andric case Mips::BNEZC: case Mips::BNEZC_MMR6:
58970b57cec5SDimitry Andric case Mips::BLEZC64:
58980b57cec5SDimitry Andric case Mips::BGEZC64:
58990b57cec5SDimitry Andric case Mips::BGTZC64:
59000b57cec5SDimitry Andric case Mips::BLTZC64:
59010b57cec5SDimitry Andric case Mips::BEQZC64:
59020b57cec5SDimitry Andric case Mips::BNEZC64:
59030b57cec5SDimitry Andric if (Inst.getOperand(0).getReg() == Mips::ZERO ||
59040b57cec5SDimitry Andric Inst.getOperand(0).getReg() == Mips::ZERO_64)
59050b57cec5SDimitry Andric return Match_RequiresNoZeroRegister;
59060b57cec5SDimitry Andric return Match_Success;
59070b57cec5SDimitry Andric case Mips::BGEC: case Mips::BGEC_MMR6:
59080b57cec5SDimitry Andric case Mips::BLTC: case Mips::BLTC_MMR6:
59090b57cec5SDimitry Andric case Mips::BGEUC: case Mips::BGEUC_MMR6:
59100b57cec5SDimitry Andric case Mips::BLTUC: case Mips::BLTUC_MMR6:
59110b57cec5SDimitry Andric case Mips::BEQC: case Mips::BEQC_MMR6:
59120b57cec5SDimitry Andric case Mips::BNEC: case Mips::BNEC_MMR6:
59130b57cec5SDimitry Andric case Mips::BGEC64:
59140b57cec5SDimitry Andric case Mips::BLTC64:
59150b57cec5SDimitry Andric case Mips::BGEUC64:
59160b57cec5SDimitry Andric case Mips::BLTUC64:
59170b57cec5SDimitry Andric case Mips::BEQC64:
59180b57cec5SDimitry Andric case Mips::BNEC64:
59190b57cec5SDimitry Andric if (Inst.getOperand(0).getReg() == Mips::ZERO ||
59200b57cec5SDimitry Andric Inst.getOperand(0).getReg() == Mips::ZERO_64)
59210b57cec5SDimitry Andric return Match_RequiresNoZeroRegister;
59220b57cec5SDimitry Andric if (Inst.getOperand(1).getReg() == Mips::ZERO ||
59230b57cec5SDimitry Andric Inst.getOperand(1).getReg() == Mips::ZERO_64)
59240b57cec5SDimitry Andric return Match_RequiresNoZeroRegister;
59250b57cec5SDimitry Andric if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
59260b57cec5SDimitry Andric return Match_RequiresDifferentOperands;
59270b57cec5SDimitry Andric return Match_Success;
59280b57cec5SDimitry Andric case Mips::DINS: {
59290b57cec5SDimitry Andric assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
59300b57cec5SDimitry Andric "Operands must be immediates for dins!");
59310b57cec5SDimitry Andric const signed Pos = Inst.getOperand(2).getImm();
59320b57cec5SDimitry Andric const signed Size = Inst.getOperand(3).getImm();
59330b57cec5SDimitry Andric if ((0 > (Pos + Size)) || ((Pos + Size) > 32))
59340b57cec5SDimitry Andric return Match_RequiresPosSizeRange0_32;
59350b57cec5SDimitry Andric return Match_Success;
59360b57cec5SDimitry Andric }
59370b57cec5SDimitry Andric case Mips::DINSM:
59380b57cec5SDimitry Andric case Mips::DINSU: {
59390b57cec5SDimitry Andric assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
59400b57cec5SDimitry Andric "Operands must be immediates for dinsm/dinsu!");
59410b57cec5SDimitry Andric const signed Pos = Inst.getOperand(2).getImm();
59420b57cec5SDimitry Andric const signed Size = Inst.getOperand(3).getImm();
59430b57cec5SDimitry Andric if ((32 >= (Pos + Size)) || ((Pos + Size) > 64))
59440b57cec5SDimitry Andric return Match_RequiresPosSizeRange33_64;
59450b57cec5SDimitry Andric return Match_Success;
59460b57cec5SDimitry Andric }
59470b57cec5SDimitry Andric case Mips::DEXT: {
59480b57cec5SDimitry Andric assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
59490b57cec5SDimitry Andric "Operands must be immediates for DEXTM!");
59500b57cec5SDimitry Andric const signed Pos = Inst.getOperand(2).getImm();
59510b57cec5SDimitry Andric const signed Size = Inst.getOperand(3).getImm();
59520b57cec5SDimitry Andric if ((1 > (Pos + Size)) || ((Pos + Size) > 63))
59530b57cec5SDimitry Andric return Match_RequiresPosSizeUImm6;
59540b57cec5SDimitry Andric return Match_Success;
59550b57cec5SDimitry Andric }
59560b57cec5SDimitry Andric case Mips::DEXTM:
59570b57cec5SDimitry Andric case Mips::DEXTU: {
59580b57cec5SDimitry Andric assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
59590b57cec5SDimitry Andric "Operands must be immediates for dextm/dextu!");
59600b57cec5SDimitry Andric const signed Pos = Inst.getOperand(2).getImm();
59610b57cec5SDimitry Andric const signed Size = Inst.getOperand(3).getImm();
59620b57cec5SDimitry Andric if ((32 > (Pos + Size)) || ((Pos + Size) > 64))
59630b57cec5SDimitry Andric return Match_RequiresPosSizeRange33_64;
59640b57cec5SDimitry Andric return Match_Success;
59650b57cec5SDimitry Andric }
59660b57cec5SDimitry Andric case Mips::CRC32B: case Mips::CRC32CB:
59670b57cec5SDimitry Andric case Mips::CRC32H: case Mips::CRC32CH:
59680b57cec5SDimitry Andric case Mips::CRC32W: case Mips::CRC32CW:
59690b57cec5SDimitry Andric case Mips::CRC32D: case Mips::CRC32CD:
59700b57cec5SDimitry Andric if (Inst.getOperand(0).getReg() != Inst.getOperand(2).getReg())
59710b57cec5SDimitry Andric return Match_RequiresSameSrcAndDst;
59720b57cec5SDimitry Andric return Match_Success;
59730b57cec5SDimitry Andric }
59740b57cec5SDimitry Andric
5975bdd1243dSDimitry Andric uint64_t TSFlags = MII.get(Inst.getOpcode()).TSFlags;
59760b57cec5SDimitry Andric if ((TSFlags & MipsII::HasFCCRegOperand) &&
59770b57cec5SDimitry Andric (Inst.getOperand(0).getReg() != Mips::FCC0) && !hasEightFccRegisters())
59780b57cec5SDimitry Andric return Match_NoFCCRegisterForCurrentISA;
59790b57cec5SDimitry Andric
59800b57cec5SDimitry Andric return Match_Success;
59810b57cec5SDimitry Andric
59820b57cec5SDimitry Andric }
59830b57cec5SDimitry Andric
RefineErrorLoc(const SMLoc Loc,const OperandVector & Operands,uint64_t ErrorInfo)59840b57cec5SDimitry Andric static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
59850b57cec5SDimitry Andric uint64_t ErrorInfo) {
59860b57cec5SDimitry Andric if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
59870b57cec5SDimitry Andric SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
59880b57cec5SDimitry Andric if (ErrorLoc == SMLoc())
59890b57cec5SDimitry Andric return Loc;
59900b57cec5SDimitry Andric return ErrorLoc;
59910b57cec5SDimitry Andric }
59920b57cec5SDimitry Andric return Loc;
59930b57cec5SDimitry Andric }
59940b57cec5SDimitry Andric
MatchAndEmitInstruction(SMLoc IDLoc,unsigned & Opcode,OperandVector & Operands,MCStreamer & Out,uint64_t & ErrorInfo,bool MatchingInlineAsm)59950b57cec5SDimitry Andric bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
59960b57cec5SDimitry Andric OperandVector &Operands,
59970b57cec5SDimitry Andric MCStreamer &Out,
59980b57cec5SDimitry Andric uint64_t &ErrorInfo,
59990b57cec5SDimitry Andric bool MatchingInlineAsm) {
60000b57cec5SDimitry Andric MCInst Inst;
60010b57cec5SDimitry Andric unsigned MatchResult =
60020b57cec5SDimitry Andric MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
60030b57cec5SDimitry Andric
60040b57cec5SDimitry Andric switch (MatchResult) {
60050b57cec5SDimitry Andric case Match_Success:
60060b57cec5SDimitry Andric if (processInstruction(Inst, IDLoc, Out, STI))
60070b57cec5SDimitry Andric return true;
60080b57cec5SDimitry Andric return false;
60090b57cec5SDimitry Andric case Match_MissingFeature:
60100b57cec5SDimitry Andric Error(IDLoc, "instruction requires a CPU feature not currently enabled");
60110b57cec5SDimitry Andric return true;
6012bdd1243dSDimitry Andric case Match_InvalidTiedOperand:
6013bdd1243dSDimitry Andric Error(IDLoc, "operand must match destination register");
6014bdd1243dSDimitry Andric return true;
60150b57cec5SDimitry Andric case Match_InvalidOperand: {
60160b57cec5SDimitry Andric SMLoc ErrorLoc = IDLoc;
60170b57cec5SDimitry Andric if (ErrorInfo != ~0ULL) {
60180b57cec5SDimitry Andric if (ErrorInfo >= Operands.size())
60190b57cec5SDimitry Andric return Error(IDLoc, "too few operands for instruction");
60200b57cec5SDimitry Andric
60210b57cec5SDimitry Andric ErrorLoc = Operands[ErrorInfo]->getStartLoc();
60220b57cec5SDimitry Andric if (ErrorLoc == SMLoc())
60230b57cec5SDimitry Andric ErrorLoc = IDLoc;
60240b57cec5SDimitry Andric }
60250b57cec5SDimitry Andric
60260b57cec5SDimitry Andric return Error(ErrorLoc, "invalid operand for instruction");
60270b57cec5SDimitry Andric }
60280b57cec5SDimitry Andric case Match_NonZeroOperandForSync:
60290b57cec5SDimitry Andric return Error(IDLoc,
60300b57cec5SDimitry Andric "s-type must be zero or unspecified for pre-MIPS32 ISAs");
60310b57cec5SDimitry Andric case Match_NonZeroOperandForMTCX:
60320b57cec5SDimitry Andric return Error(IDLoc, "selector must be zero for pre-MIPS32 ISAs");
60330b57cec5SDimitry Andric case Match_MnemonicFail:
60340b57cec5SDimitry Andric return Error(IDLoc, "invalid instruction");
60350b57cec5SDimitry Andric case Match_RequiresDifferentSrcAndDst:
60360b57cec5SDimitry Andric return Error(IDLoc, "source and destination must be different");
60370b57cec5SDimitry Andric case Match_RequiresDifferentOperands:
60380b57cec5SDimitry Andric return Error(IDLoc, "registers must be different");
60390b57cec5SDimitry Andric case Match_RequiresNoZeroRegister:
60400b57cec5SDimitry Andric return Error(IDLoc, "invalid operand ($zero) for instruction");
60410b57cec5SDimitry Andric case Match_RequiresSameSrcAndDst:
60420b57cec5SDimitry Andric return Error(IDLoc, "source and destination must match");
60430b57cec5SDimitry Andric case Match_NoFCCRegisterForCurrentISA:
60440b57cec5SDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
60450b57cec5SDimitry Andric "non-zero fcc register doesn't exist in current ISA level");
60460b57cec5SDimitry Andric case Match_Immz:
60470b57cec5SDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
60480b57cec5SDimitry Andric case Match_UImm1_0:
60490b57cec5SDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
60500b57cec5SDimitry Andric "expected 1-bit unsigned immediate");
60510b57cec5SDimitry Andric case Match_UImm2_0:
60520b57cec5SDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
60530b57cec5SDimitry Andric "expected 2-bit unsigned immediate");
60540b57cec5SDimitry Andric case Match_UImm2_1:
60550b57cec5SDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
60560b57cec5SDimitry Andric "expected immediate in range 1 .. 4");
60570b57cec5SDimitry Andric case Match_UImm3_0:
60580b57cec5SDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
60590b57cec5SDimitry Andric "expected 3-bit unsigned immediate");
60600b57cec5SDimitry Andric case Match_UImm4_0:
60610b57cec5SDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
60620b57cec5SDimitry Andric "expected 4-bit unsigned immediate");
60630b57cec5SDimitry Andric case Match_SImm4_0:
60640b57cec5SDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
60650b57cec5SDimitry Andric "expected 4-bit signed immediate");
60660b57cec5SDimitry Andric case Match_UImm5_0:
60670b57cec5SDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
60680b57cec5SDimitry Andric "expected 5-bit unsigned immediate");
60690b57cec5SDimitry Andric case Match_SImm5_0:
60700b57cec5SDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
60710b57cec5SDimitry Andric "expected 5-bit signed immediate");
60720b57cec5SDimitry Andric case Match_UImm5_1:
60730b57cec5SDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
60740b57cec5SDimitry Andric "expected immediate in range 1 .. 32");
60750b57cec5SDimitry Andric case Match_UImm5_32:
60760b57cec5SDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
60770b57cec5SDimitry Andric "expected immediate in range 32 .. 63");
60780b57cec5SDimitry Andric case Match_UImm5_33:
60790b57cec5SDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
60800b57cec5SDimitry Andric "expected immediate in range 33 .. 64");
60810b57cec5SDimitry Andric case Match_UImm5_0_Report_UImm6:
60820b57cec5SDimitry Andric // This is used on UImm5 operands that have a corresponding UImm5_32
60830b57cec5SDimitry Andric // operand to avoid confusing the user.
60840b57cec5SDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
60850b57cec5SDimitry Andric "expected 6-bit unsigned immediate");
60860b57cec5SDimitry Andric case Match_UImm5_Lsl2:
60870b57cec5SDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
60880b57cec5SDimitry Andric "expected both 7-bit unsigned immediate and multiple of 4");
60890b57cec5SDimitry Andric case Match_UImmRange2_64:
60900b57cec5SDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
60910b57cec5SDimitry Andric "expected immediate in range 2 .. 64");
60920b57cec5SDimitry Andric case Match_UImm6_0:
60930b57cec5SDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
60940b57cec5SDimitry Andric "expected 6-bit unsigned immediate");
60950b57cec5SDimitry Andric case Match_UImm6_Lsl2:
60960b57cec5SDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
60970b57cec5SDimitry Andric "expected both 8-bit unsigned immediate and multiple of 4");
60980b57cec5SDimitry Andric case Match_SImm6_0:
60990b57cec5SDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
61000b57cec5SDimitry Andric "expected 6-bit signed immediate");
61010b57cec5SDimitry Andric case Match_UImm7_0:
61020b57cec5SDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
61030b57cec5SDimitry Andric "expected 7-bit unsigned immediate");
61040b57cec5SDimitry Andric case Match_UImm7_N1:
61050b57cec5SDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
61060b57cec5SDimitry Andric "expected immediate in range -1 .. 126");
61070b57cec5SDimitry Andric case Match_SImm7_Lsl2:
61080b57cec5SDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
61090b57cec5SDimitry Andric "expected both 9-bit signed immediate and multiple of 4");
61100b57cec5SDimitry Andric case Match_UImm8_0:
61110b57cec5SDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
61120b57cec5SDimitry Andric "expected 8-bit unsigned immediate");
61130b57cec5SDimitry Andric case Match_UImm10_0:
61140b57cec5SDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
61150b57cec5SDimitry Andric "expected 10-bit unsigned immediate");
61160b57cec5SDimitry Andric case Match_SImm10_0:
61170b57cec5SDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
61180b57cec5SDimitry Andric "expected 10-bit signed immediate");
61190b57cec5SDimitry Andric case Match_SImm11_0:
61200b57cec5SDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
61210b57cec5SDimitry Andric "expected 11-bit signed immediate");
61220b57cec5SDimitry Andric case Match_UImm16:
61230b57cec5SDimitry Andric case Match_UImm16_Relaxed:
61240b57cec5SDimitry Andric case Match_UImm16_AltRelaxed:
61250b57cec5SDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
61260b57cec5SDimitry Andric "expected 16-bit unsigned immediate");
61270b57cec5SDimitry Andric case Match_SImm16:
61280b57cec5SDimitry Andric case Match_SImm16_Relaxed:
61290b57cec5SDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
61300b57cec5SDimitry Andric "expected 16-bit signed immediate");
61310b57cec5SDimitry Andric case Match_SImm19_Lsl2:
61320b57cec5SDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
61330b57cec5SDimitry Andric "expected both 19-bit signed immediate and multiple of 4");
61340b57cec5SDimitry Andric case Match_UImm20_0:
61350b57cec5SDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
61360b57cec5SDimitry Andric "expected 20-bit unsigned immediate");
61370b57cec5SDimitry Andric case Match_UImm26_0:
61380b57cec5SDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
61390b57cec5SDimitry Andric "expected 26-bit unsigned immediate");
61400b57cec5SDimitry Andric case Match_SImm32:
61410b57cec5SDimitry Andric case Match_SImm32_Relaxed:
61420b57cec5SDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
61430b57cec5SDimitry Andric "expected 32-bit signed immediate");
61440b57cec5SDimitry Andric case Match_UImm32_Coerced:
61450b57cec5SDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
61460b57cec5SDimitry Andric "expected 32-bit immediate");
61470b57cec5SDimitry Andric case Match_MemSImm9:
61480b57cec5SDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
61490b57cec5SDimitry Andric "expected memory with 9-bit signed offset");
61500b57cec5SDimitry Andric case Match_MemSImm10:
61510b57cec5SDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
61520b57cec5SDimitry Andric "expected memory with 10-bit signed offset");
61530b57cec5SDimitry Andric case Match_MemSImm10Lsl1:
61540b57cec5SDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
61550b57cec5SDimitry Andric "expected memory with 11-bit signed offset and multiple of 2");
61560b57cec5SDimitry Andric case Match_MemSImm10Lsl2:
61570b57cec5SDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
61580b57cec5SDimitry Andric "expected memory with 12-bit signed offset and multiple of 4");
61590b57cec5SDimitry Andric case Match_MemSImm10Lsl3:
61600b57cec5SDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
61610b57cec5SDimitry Andric "expected memory with 13-bit signed offset and multiple of 8");
61620b57cec5SDimitry Andric case Match_MemSImm11:
61630b57cec5SDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
61640b57cec5SDimitry Andric "expected memory with 11-bit signed offset");
61650b57cec5SDimitry Andric case Match_MemSImm12:
61660b57cec5SDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
61670b57cec5SDimitry Andric "expected memory with 12-bit signed offset");
61680b57cec5SDimitry Andric case Match_MemSImm16:
61690b57cec5SDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
61700b57cec5SDimitry Andric "expected memory with 16-bit signed offset");
61710b57cec5SDimitry Andric case Match_MemSImmPtr:
61720b57cec5SDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
61730b57cec5SDimitry Andric "expected memory with 32-bit signed offset");
61740b57cec5SDimitry Andric case Match_RequiresPosSizeRange0_32: {
61750b57cec5SDimitry Andric SMLoc ErrorStart = Operands[3]->getStartLoc();
61760b57cec5SDimitry Andric SMLoc ErrorEnd = Operands[4]->getEndLoc();
61770b57cec5SDimitry Andric return Error(ErrorStart, "size plus position are not in the range 0 .. 32",
61780b57cec5SDimitry Andric SMRange(ErrorStart, ErrorEnd));
61790b57cec5SDimitry Andric }
61800b57cec5SDimitry Andric case Match_RequiresPosSizeUImm6: {
61810b57cec5SDimitry Andric SMLoc ErrorStart = Operands[3]->getStartLoc();
61820b57cec5SDimitry Andric SMLoc ErrorEnd = Operands[4]->getEndLoc();
61830b57cec5SDimitry Andric return Error(ErrorStart, "size plus position are not in the range 1 .. 63",
61840b57cec5SDimitry Andric SMRange(ErrorStart, ErrorEnd));
61850b57cec5SDimitry Andric }
61860b57cec5SDimitry Andric case Match_RequiresPosSizeRange33_64: {
61870b57cec5SDimitry Andric SMLoc ErrorStart = Operands[3]->getStartLoc();
61880b57cec5SDimitry Andric SMLoc ErrorEnd = Operands[4]->getEndLoc();
61890b57cec5SDimitry Andric return Error(ErrorStart, "size plus position are not in the range 33 .. 64",
61900b57cec5SDimitry Andric SMRange(ErrorStart, ErrorEnd));
61910b57cec5SDimitry Andric }
61920b57cec5SDimitry Andric }
61930b57cec5SDimitry Andric
61940b57cec5SDimitry Andric llvm_unreachable("Implement any new match types added!");
61950b57cec5SDimitry Andric }
61960b57cec5SDimitry Andric
warnIfRegIndexIsAT(unsigned RegIndex,SMLoc Loc)61970b57cec5SDimitry Andric void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
61980b57cec5SDimitry Andric if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
61990b57cec5SDimitry Andric Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
62000b57cec5SDimitry Andric ") without \".set noat\"");
62010b57cec5SDimitry Andric }
62020b57cec5SDimitry Andric
warnIfNoMacro(SMLoc Loc)62030b57cec5SDimitry Andric void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
62040b57cec5SDimitry Andric if (!AssemblerOptions.back()->isMacro())
62050b57cec5SDimitry Andric Warning(Loc, "macro instruction expanded into multiple instructions");
62060b57cec5SDimitry Andric }
62070b57cec5SDimitry Andric
ConvertXWPOperands(MCInst & Inst,const OperandVector & Operands)62080b57cec5SDimitry Andric void MipsAsmParser::ConvertXWPOperands(MCInst &Inst,
62090b57cec5SDimitry Andric const OperandVector &Operands) {
62100b57cec5SDimitry Andric assert(
62110b57cec5SDimitry Andric (Inst.getOpcode() == Mips::LWP_MM || Inst.getOpcode() == Mips::SWP_MM) &&
62120b57cec5SDimitry Andric "Unexpected instruction!");
62130b57cec5SDimitry Andric ((MipsOperand &)*Operands[1]).addGPR32ZeroAsmRegOperands(Inst, 1);
62140b57cec5SDimitry Andric int NextReg = nextReg(((MipsOperand &)*Operands[1]).getGPR32Reg());
62150b57cec5SDimitry Andric Inst.addOperand(MCOperand::createReg(NextReg));
62160b57cec5SDimitry Andric ((MipsOperand &)*Operands[2]).addMemOperands(Inst, 2);
62170b57cec5SDimitry Andric }
62180b57cec5SDimitry Andric
62190b57cec5SDimitry Andric void
printWarningWithFixIt(const Twine & Msg,const Twine & FixMsg,SMRange Range,bool ShowColors)62200b57cec5SDimitry Andric MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
62210b57cec5SDimitry Andric SMRange Range, bool ShowColors) {
62220b57cec5SDimitry Andric getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
62230b57cec5SDimitry Andric Range, SMFixIt(Range, FixMsg),
62240b57cec5SDimitry Andric ShowColors);
62250b57cec5SDimitry Andric }
62260b57cec5SDimitry Andric
matchCPURegisterName(StringRef Name)62270b57cec5SDimitry Andric int MipsAsmParser::matchCPURegisterName(StringRef Name) {
62280b57cec5SDimitry Andric int CC;
62290b57cec5SDimitry Andric
62300b57cec5SDimitry Andric CC = StringSwitch<unsigned>(Name)
62310b57cec5SDimitry Andric .Case("zero", 0)
62320b57cec5SDimitry Andric .Cases("at", "AT", 1)
62330b57cec5SDimitry Andric .Case("a0", 4)
62340b57cec5SDimitry Andric .Case("a1", 5)
62350b57cec5SDimitry Andric .Case("a2", 6)
62360b57cec5SDimitry Andric .Case("a3", 7)
62370b57cec5SDimitry Andric .Case("v0", 2)
62380b57cec5SDimitry Andric .Case("v1", 3)
62390b57cec5SDimitry Andric .Case("s0", 16)
62400b57cec5SDimitry Andric .Case("s1", 17)
62410b57cec5SDimitry Andric .Case("s2", 18)
62420b57cec5SDimitry Andric .Case("s3", 19)
62430b57cec5SDimitry Andric .Case("s4", 20)
62440b57cec5SDimitry Andric .Case("s5", 21)
62450b57cec5SDimitry Andric .Case("s6", 22)
62460b57cec5SDimitry Andric .Case("s7", 23)
62470b57cec5SDimitry Andric .Case("k0", 26)
62480b57cec5SDimitry Andric .Case("k1", 27)
62490b57cec5SDimitry Andric .Case("gp", 28)
62500b57cec5SDimitry Andric .Case("sp", 29)
62510b57cec5SDimitry Andric .Case("fp", 30)
62520b57cec5SDimitry Andric .Case("s8", 30)
62530b57cec5SDimitry Andric .Case("ra", 31)
62540b57cec5SDimitry Andric .Case("t0", 8)
62550b57cec5SDimitry Andric .Case("t1", 9)
62560b57cec5SDimitry Andric .Case("t2", 10)
62570b57cec5SDimitry Andric .Case("t3", 11)
62580b57cec5SDimitry Andric .Case("t4", 12)
62590b57cec5SDimitry Andric .Case("t5", 13)
62600b57cec5SDimitry Andric .Case("t6", 14)
62610b57cec5SDimitry Andric .Case("t7", 15)
62620b57cec5SDimitry Andric .Case("t8", 24)
62630b57cec5SDimitry Andric .Case("t9", 25)
62640b57cec5SDimitry Andric .Default(-1);
62650b57cec5SDimitry Andric
62660b57cec5SDimitry Andric if (!(isABI_N32() || isABI_N64()))
62670b57cec5SDimitry Andric return CC;
62680b57cec5SDimitry Andric
62690b57cec5SDimitry Andric if (12 <= CC && CC <= 15) {
62700b57cec5SDimitry Andric // Name is one of t4-t7
62710b57cec5SDimitry Andric AsmToken RegTok = getLexer().peekTok();
62720b57cec5SDimitry Andric SMRange RegRange = RegTok.getLocRange();
62730b57cec5SDimitry Andric
62740b57cec5SDimitry Andric StringRef FixedName = StringSwitch<StringRef>(Name)
62750b57cec5SDimitry Andric .Case("t4", "t0")
62760b57cec5SDimitry Andric .Case("t5", "t1")
62770b57cec5SDimitry Andric .Case("t6", "t2")
62780b57cec5SDimitry Andric .Case("t7", "t3")
62790b57cec5SDimitry Andric .Default("");
62800b57cec5SDimitry Andric assert(FixedName != "" && "Register name is not one of t4-t7.");
62810b57cec5SDimitry Andric
62820b57cec5SDimitry Andric printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
62830b57cec5SDimitry Andric "Did you mean $" + FixedName + "?", RegRange);
62840b57cec5SDimitry Andric }
62850b57cec5SDimitry Andric
62860b57cec5SDimitry Andric // Although SGI documentation just cuts out t0-t3 for n32/n64,
62870b57cec5SDimitry Andric // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
62880b57cec5SDimitry Andric // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
62890b57cec5SDimitry Andric if (8 <= CC && CC <= 11)
62900b57cec5SDimitry Andric CC += 4;
62910b57cec5SDimitry Andric
62920b57cec5SDimitry Andric if (CC == -1)
62930b57cec5SDimitry Andric CC = StringSwitch<unsigned>(Name)
62940b57cec5SDimitry Andric .Case("a4", 8)
62950b57cec5SDimitry Andric .Case("a5", 9)
62960b57cec5SDimitry Andric .Case("a6", 10)
62970b57cec5SDimitry Andric .Case("a7", 11)
62980b57cec5SDimitry Andric .Case("kt0", 26)
62990b57cec5SDimitry Andric .Case("kt1", 27)
63000b57cec5SDimitry Andric .Default(-1);
63010b57cec5SDimitry Andric
63020b57cec5SDimitry Andric return CC;
63030b57cec5SDimitry Andric }
63040b57cec5SDimitry Andric
matchHWRegsRegisterName(StringRef Name)63050b57cec5SDimitry Andric int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
63060b57cec5SDimitry Andric int CC;
63070b57cec5SDimitry Andric
63080b57cec5SDimitry Andric CC = StringSwitch<unsigned>(Name)
63090b57cec5SDimitry Andric .Case("hwr_cpunum", 0)
63100b57cec5SDimitry Andric .Case("hwr_synci_step", 1)
63110b57cec5SDimitry Andric .Case("hwr_cc", 2)
63120b57cec5SDimitry Andric .Case("hwr_ccres", 3)
63130b57cec5SDimitry Andric .Case("hwr_ulr", 29)
63140b57cec5SDimitry Andric .Default(-1);
63150b57cec5SDimitry Andric
63160b57cec5SDimitry Andric return CC;
63170b57cec5SDimitry Andric }
63180b57cec5SDimitry Andric
matchFPURegisterName(StringRef Name)63190b57cec5SDimitry Andric int MipsAsmParser::matchFPURegisterName(StringRef Name) {
63200b57cec5SDimitry Andric if (Name[0] == 'f') {
63210b57cec5SDimitry Andric StringRef NumString = Name.substr(1);
63220b57cec5SDimitry Andric unsigned IntVal;
63230b57cec5SDimitry Andric if (NumString.getAsInteger(10, IntVal))
63240b57cec5SDimitry Andric return -1; // This is not an integer.
63250b57cec5SDimitry Andric if (IntVal > 31) // Maximum index for fpu register.
63260b57cec5SDimitry Andric return -1;
63270b57cec5SDimitry Andric return IntVal;
63280b57cec5SDimitry Andric }
63290b57cec5SDimitry Andric return -1;
63300b57cec5SDimitry Andric }
63310b57cec5SDimitry Andric
matchFCCRegisterName(StringRef Name)63320b57cec5SDimitry Andric int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
63335f757f3fSDimitry Andric if (Name.starts_with("fcc")) {
63340b57cec5SDimitry Andric StringRef NumString = Name.substr(3);
63350b57cec5SDimitry Andric unsigned IntVal;
63360b57cec5SDimitry Andric if (NumString.getAsInteger(10, IntVal))
63370b57cec5SDimitry Andric return -1; // This is not an integer.
63380b57cec5SDimitry Andric if (IntVal > 7) // There are only 8 fcc registers.
63390b57cec5SDimitry Andric return -1;
63400b57cec5SDimitry Andric return IntVal;
63410b57cec5SDimitry Andric }
63420b57cec5SDimitry Andric return -1;
63430b57cec5SDimitry Andric }
63440b57cec5SDimitry Andric
matchACRegisterName(StringRef Name)63450b57cec5SDimitry Andric int MipsAsmParser::matchACRegisterName(StringRef Name) {
63465f757f3fSDimitry Andric if (Name.starts_with("ac")) {
63470b57cec5SDimitry Andric StringRef NumString = Name.substr(2);
63480b57cec5SDimitry Andric unsigned IntVal;
63490b57cec5SDimitry Andric if (NumString.getAsInteger(10, IntVal))
63500b57cec5SDimitry Andric return -1; // This is not an integer.
63510b57cec5SDimitry Andric if (IntVal > 3) // There are only 3 acc registers.
63520b57cec5SDimitry Andric return -1;
63530b57cec5SDimitry Andric return IntVal;
63540b57cec5SDimitry Andric }
63550b57cec5SDimitry Andric return -1;
63560b57cec5SDimitry Andric }
63570b57cec5SDimitry Andric
matchMSA128RegisterName(StringRef Name)63580b57cec5SDimitry Andric int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
63590b57cec5SDimitry Andric unsigned IntVal;
63600b57cec5SDimitry Andric
63610b57cec5SDimitry Andric if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
63620b57cec5SDimitry Andric return -1;
63630b57cec5SDimitry Andric
63640b57cec5SDimitry Andric if (IntVal > 31)
63650b57cec5SDimitry Andric return -1;
63660b57cec5SDimitry Andric
63670b57cec5SDimitry Andric return IntVal;
63680b57cec5SDimitry Andric }
63690b57cec5SDimitry Andric
matchMSA128CtrlRegisterName(StringRef Name)63700b57cec5SDimitry Andric int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
63710b57cec5SDimitry Andric int CC;
63720b57cec5SDimitry Andric
63730b57cec5SDimitry Andric CC = StringSwitch<unsigned>(Name)
63740b57cec5SDimitry Andric .Case("msair", 0)
63750b57cec5SDimitry Andric .Case("msacsr", 1)
63760b57cec5SDimitry Andric .Case("msaaccess", 2)
63770b57cec5SDimitry Andric .Case("msasave", 3)
63780b57cec5SDimitry Andric .Case("msamodify", 4)
63790b57cec5SDimitry Andric .Case("msarequest", 5)
63800b57cec5SDimitry Andric .Case("msamap", 6)
63810b57cec5SDimitry Andric .Case("msaunmap", 7)
63820b57cec5SDimitry Andric .Default(-1);
63830b57cec5SDimitry Andric
63840b57cec5SDimitry Andric return CC;
63850b57cec5SDimitry Andric }
63860b57cec5SDimitry Andric
canUseATReg()63870b57cec5SDimitry Andric bool MipsAsmParser::canUseATReg() {
63880b57cec5SDimitry Andric return AssemblerOptions.back()->getATRegIndex() != 0;
63890b57cec5SDimitry Andric }
63900b57cec5SDimitry Andric
getATReg(SMLoc Loc)63910b57cec5SDimitry Andric unsigned MipsAsmParser::getATReg(SMLoc Loc) {
63920b57cec5SDimitry Andric unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
63930b57cec5SDimitry Andric if (ATIndex == 0) {
63940b57cec5SDimitry Andric reportParseError(Loc,
63950b57cec5SDimitry Andric "pseudo-instruction requires $at, which is not available");
63960b57cec5SDimitry Andric return 0;
63970b57cec5SDimitry Andric }
63980b57cec5SDimitry Andric unsigned AT = getReg(
63990b57cec5SDimitry Andric (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
64000b57cec5SDimitry Andric return AT;
64010b57cec5SDimitry Andric }
64020b57cec5SDimitry Andric
getReg(int RC,int RegNo)64030b57cec5SDimitry Andric unsigned MipsAsmParser::getReg(int RC, int RegNo) {
64040b57cec5SDimitry Andric return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
64050b57cec5SDimitry Andric }
64060b57cec5SDimitry Andric
parseOperand(OperandVector & Operands,StringRef Mnemonic)64070b57cec5SDimitry Andric bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
64080b57cec5SDimitry Andric MCAsmParser &Parser = getParser();
64090b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "parseOperand\n");
64100b57cec5SDimitry Andric
64110b57cec5SDimitry Andric // Check if the current operand has a custom associated parser, if so, try to
64120b57cec5SDimitry Andric // custom parse the operand, or fallback to the general approach.
641306c3fb27SDimitry Andric ParseStatus Res = MatchOperandParserImpl(Operands, Mnemonic);
641406c3fb27SDimitry Andric if (Res.isSuccess())
64150b57cec5SDimitry Andric return false;
64160b57cec5SDimitry Andric // If there wasn't a custom match, try the generic matcher below. Otherwise,
64170b57cec5SDimitry Andric // there was a match, but an error occurred, in which case, just return that
64180b57cec5SDimitry Andric // the operand parsing failed.
641906c3fb27SDimitry Andric if (Res.isFailure())
64200b57cec5SDimitry Andric return true;
64210b57cec5SDimitry Andric
64220b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << ".. Generic Parser\n");
64230b57cec5SDimitry Andric
64240b57cec5SDimitry Andric switch (getLexer().getKind()) {
64250b57cec5SDimitry Andric case AsmToken::Dollar: {
64260b57cec5SDimitry Andric // Parse the register.
64270b57cec5SDimitry Andric SMLoc S = Parser.getTok().getLoc();
64280b57cec5SDimitry Andric
64290b57cec5SDimitry Andric // Almost all registers have been parsed by custom parsers. There is only
64300b57cec5SDimitry Andric // one exception to this. $zero (and it's alias $0) will reach this point
64310b57cec5SDimitry Andric // for div, divu, and similar instructions because it is not an operand
64320b57cec5SDimitry Andric // to the instruction definition but an explicit register. Special case
64330b57cec5SDimitry Andric // this situation for now.
643406c3fb27SDimitry Andric if (!parseAnyRegister(Operands).isNoMatch())
64350b57cec5SDimitry Andric return false;
64360b57cec5SDimitry Andric
64370b57cec5SDimitry Andric // Maybe it is a symbol reference.
64380b57cec5SDimitry Andric StringRef Identifier;
64390b57cec5SDimitry Andric if (Parser.parseIdentifier(Identifier))
64400b57cec5SDimitry Andric return true;
64410b57cec5SDimitry Andric
64420b57cec5SDimitry Andric SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
644374626c16SDimitry Andric MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
64440b57cec5SDimitry Andric // Otherwise create a symbol reference.
644506c3fb27SDimitry Andric const MCExpr *SymRef =
64460b57cec5SDimitry Andric MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
64470b57cec5SDimitry Andric
644806c3fb27SDimitry Andric Operands.push_back(MipsOperand::CreateImm(SymRef, S, E, *this));
64490b57cec5SDimitry Andric return false;
64500b57cec5SDimitry Andric }
64510b57cec5SDimitry Andric default: {
64520b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << ".. generic integer expression\n");
64530b57cec5SDimitry Andric
64540b57cec5SDimitry Andric const MCExpr *Expr;
64550b57cec5SDimitry Andric SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
64560b57cec5SDimitry Andric if (getParser().parseExpression(Expr))
64570b57cec5SDimitry Andric return true;
64580b57cec5SDimitry Andric
64590b57cec5SDimitry Andric SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
64600b57cec5SDimitry Andric
64610b57cec5SDimitry Andric Operands.push_back(MipsOperand::CreateImm(Expr, S, E, *this));
64620b57cec5SDimitry Andric return false;
64630b57cec5SDimitry Andric }
64640b57cec5SDimitry Andric } // switch(getLexer().getKind())
64650b57cec5SDimitry Andric return true;
64660b57cec5SDimitry Andric }
64670b57cec5SDimitry Andric
parseRegister(MCRegister & Reg,SMLoc & StartLoc,SMLoc & EndLoc)64685f757f3fSDimitry Andric bool MipsAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,
64690b57cec5SDimitry Andric SMLoc &EndLoc) {
64705f757f3fSDimitry Andric return !tryParseRegister(Reg, StartLoc, EndLoc).isSuccess();
64715ffd83dbSDimitry Andric }
64725ffd83dbSDimitry Andric
tryParseRegister(MCRegister & Reg,SMLoc & StartLoc,SMLoc & EndLoc)64735f757f3fSDimitry Andric ParseStatus MipsAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
64745ffd83dbSDimitry Andric SMLoc &EndLoc) {
64750b57cec5SDimitry Andric SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
647606c3fb27SDimitry Andric ParseStatus Res = parseAnyRegister(Operands);
647706c3fb27SDimitry Andric if (Res.isSuccess()) {
64780b57cec5SDimitry Andric assert(Operands.size() == 1);
64790b57cec5SDimitry Andric MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
64800b57cec5SDimitry Andric StartLoc = Operand.getStartLoc();
64810b57cec5SDimitry Andric EndLoc = Operand.getEndLoc();
64820b57cec5SDimitry Andric
64830b57cec5SDimitry Andric // AFAIK, we only support numeric registers and named GPR's in CFI
64840b57cec5SDimitry Andric // directives.
64850b57cec5SDimitry Andric // Don't worry about eating tokens before failing. Using an unrecognised
64860b57cec5SDimitry Andric // register is a parse error.
64870b57cec5SDimitry Andric if (Operand.isGPRAsmReg()) {
64880b57cec5SDimitry Andric // Resolve to GPR32 or GPR64 appropriately.
64895f757f3fSDimitry Andric Reg = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
64900b57cec5SDimitry Andric }
64910b57cec5SDimitry Andric
64925f757f3fSDimitry Andric return (Reg == (unsigned)-1) ? ParseStatus::NoMatch : ParseStatus::Success;
64930b57cec5SDimitry Andric }
64940b57cec5SDimitry Andric
64950b57cec5SDimitry Andric assert(Operands.size() == 0);
64965f757f3fSDimitry Andric return (Reg == (unsigned)-1) ? ParseStatus::NoMatch : ParseStatus::Success;
64970b57cec5SDimitry Andric }
64980b57cec5SDimitry Andric
parseMemOffset(const MCExpr * & Res,bool isParenExpr)64990b57cec5SDimitry Andric bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
65000b57cec5SDimitry Andric SMLoc S;
65010b57cec5SDimitry Andric
65020b57cec5SDimitry Andric if (isParenExpr)
65030b57cec5SDimitry Andric return getParser().parseParenExprOfDepth(0, Res, S);
65040b57cec5SDimitry Andric return getParser().parseExpression(Res);
65050b57cec5SDimitry Andric }
65060b57cec5SDimitry Andric
parseMemOperand(OperandVector & Operands)650706c3fb27SDimitry Andric ParseStatus MipsAsmParser::parseMemOperand(OperandVector &Operands) {
65080b57cec5SDimitry Andric MCAsmParser &Parser = getParser();
65090b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "parseMemOperand\n");
65100b57cec5SDimitry Andric const MCExpr *IdVal = nullptr;
65110b57cec5SDimitry Andric SMLoc S;
65120b57cec5SDimitry Andric bool isParenExpr = false;
651306c3fb27SDimitry Andric ParseStatus Res = ParseStatus::NoMatch;
65140b57cec5SDimitry Andric // First operand is the offset.
65150b57cec5SDimitry Andric S = Parser.getTok().getLoc();
65160b57cec5SDimitry Andric
65170b57cec5SDimitry Andric if (getLexer().getKind() == AsmToken::LParen) {
65180b57cec5SDimitry Andric Parser.Lex();
65190b57cec5SDimitry Andric isParenExpr = true;
65200b57cec5SDimitry Andric }
65210b57cec5SDimitry Andric
65220b57cec5SDimitry Andric if (getLexer().getKind() != AsmToken::Dollar) {
65230b57cec5SDimitry Andric if (parseMemOffset(IdVal, isParenExpr))
652406c3fb27SDimitry Andric return ParseStatus::Failure;
65250b57cec5SDimitry Andric
65260b57cec5SDimitry Andric const AsmToken &Tok = Parser.getTok(); // Get the next token.
65270b57cec5SDimitry Andric if (Tok.isNot(AsmToken::LParen)) {
65280b57cec5SDimitry Andric MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
65290b57cec5SDimitry Andric if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
65300b57cec5SDimitry Andric SMLoc E =
65310b57cec5SDimitry Andric SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
65320b57cec5SDimitry Andric Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
653306c3fb27SDimitry Andric return ParseStatus::Success;
65340b57cec5SDimitry Andric }
65350b57cec5SDimitry Andric if (Tok.is(AsmToken::EndOfStatement)) {
65360b57cec5SDimitry Andric SMLoc E =
65370b57cec5SDimitry Andric SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
65380b57cec5SDimitry Andric
65390b57cec5SDimitry Andric // Zero register assumed, add a memory operand with ZERO as its base.
65400b57cec5SDimitry Andric // "Base" will be managed by k_Memory.
65410b57cec5SDimitry Andric auto Base = MipsOperand::createGPRReg(
65420b57cec5SDimitry Andric 0, "0", getContext().getRegisterInfo(), S, E, *this);
65430b57cec5SDimitry Andric Operands.push_back(
65440b57cec5SDimitry Andric MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
654506c3fb27SDimitry Andric return ParseStatus::Success;
65460b57cec5SDimitry Andric }
65470b57cec5SDimitry Andric MCBinaryExpr::Opcode Opcode;
65480b57cec5SDimitry Andric // GAS and LLVM treat comparison operators different. GAS will generate -1
65490b57cec5SDimitry Andric // or 0, while LLVM will generate 0 or 1. Since a comparsion operator is
65500b57cec5SDimitry Andric // highly unlikely to be found in a memory offset expression, we don't
65510b57cec5SDimitry Andric // handle them.
65520b57cec5SDimitry Andric switch (Tok.getKind()) {
65530b57cec5SDimitry Andric case AsmToken::Plus:
65540b57cec5SDimitry Andric Opcode = MCBinaryExpr::Add;
65550b57cec5SDimitry Andric Parser.Lex();
65560b57cec5SDimitry Andric break;
65570b57cec5SDimitry Andric case AsmToken::Minus:
65580b57cec5SDimitry Andric Opcode = MCBinaryExpr::Sub;
65590b57cec5SDimitry Andric Parser.Lex();
65600b57cec5SDimitry Andric break;
65610b57cec5SDimitry Andric case AsmToken::Star:
65620b57cec5SDimitry Andric Opcode = MCBinaryExpr::Mul;
65630b57cec5SDimitry Andric Parser.Lex();
65640b57cec5SDimitry Andric break;
65650b57cec5SDimitry Andric case AsmToken::Pipe:
65660b57cec5SDimitry Andric Opcode = MCBinaryExpr::Or;
65670b57cec5SDimitry Andric Parser.Lex();
65680b57cec5SDimitry Andric break;
65690b57cec5SDimitry Andric case AsmToken::Amp:
65700b57cec5SDimitry Andric Opcode = MCBinaryExpr::And;
65710b57cec5SDimitry Andric Parser.Lex();
65720b57cec5SDimitry Andric break;
65730b57cec5SDimitry Andric case AsmToken::LessLess:
65740b57cec5SDimitry Andric Opcode = MCBinaryExpr::Shl;
65750b57cec5SDimitry Andric Parser.Lex();
65760b57cec5SDimitry Andric break;
65770b57cec5SDimitry Andric case AsmToken::GreaterGreater:
65780b57cec5SDimitry Andric Opcode = MCBinaryExpr::LShr;
65790b57cec5SDimitry Andric Parser.Lex();
65800b57cec5SDimitry Andric break;
65810b57cec5SDimitry Andric case AsmToken::Caret:
65820b57cec5SDimitry Andric Opcode = MCBinaryExpr::Xor;
65830b57cec5SDimitry Andric Parser.Lex();
65840b57cec5SDimitry Andric break;
65850b57cec5SDimitry Andric case AsmToken::Slash:
65860b57cec5SDimitry Andric Opcode = MCBinaryExpr::Div;
65870b57cec5SDimitry Andric Parser.Lex();
65880b57cec5SDimitry Andric break;
65890b57cec5SDimitry Andric case AsmToken::Percent:
65900b57cec5SDimitry Andric Opcode = MCBinaryExpr::Mod;
65910b57cec5SDimitry Andric Parser.Lex();
65920b57cec5SDimitry Andric break;
65930b57cec5SDimitry Andric default:
659406c3fb27SDimitry Andric return Error(Parser.getTok().getLoc(), "'(' or expression expected");
65950b57cec5SDimitry Andric }
65960b57cec5SDimitry Andric const MCExpr * NextExpr;
65970b57cec5SDimitry Andric if (getParser().parseExpression(NextExpr))
659806c3fb27SDimitry Andric return ParseStatus::Failure;
65990b57cec5SDimitry Andric IdVal = MCBinaryExpr::create(Opcode, IdVal, NextExpr, getContext());
66000b57cec5SDimitry Andric }
66010b57cec5SDimitry Andric
66020b57cec5SDimitry Andric Parser.Lex(); // Eat the '(' token.
66030b57cec5SDimitry Andric }
66040b57cec5SDimitry Andric
66050b57cec5SDimitry Andric Res = parseAnyRegister(Operands);
660606c3fb27SDimitry Andric if (!Res.isSuccess())
66070b57cec5SDimitry Andric return Res;
66080b57cec5SDimitry Andric
660906c3fb27SDimitry Andric if (Parser.getTok().isNot(AsmToken::RParen))
661006c3fb27SDimitry Andric return Error(Parser.getTok().getLoc(), "')' expected");
66110b57cec5SDimitry Andric
66120b57cec5SDimitry Andric SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
66130b57cec5SDimitry Andric
66140b57cec5SDimitry Andric Parser.Lex(); // Eat the ')' token.
66150b57cec5SDimitry Andric
66160b57cec5SDimitry Andric if (!IdVal)
66170b57cec5SDimitry Andric IdVal = MCConstantExpr::create(0, getContext());
66180b57cec5SDimitry Andric
66190b57cec5SDimitry Andric // Replace the register operand with the memory operand.
66200b57cec5SDimitry Andric std::unique_ptr<MipsOperand> op(
66210b57cec5SDimitry Andric static_cast<MipsOperand *>(Operands.back().release()));
66220b57cec5SDimitry Andric // Remove the register from the operands.
66230b57cec5SDimitry Andric // "op" will be managed by k_Memory.
66240b57cec5SDimitry Andric Operands.pop_back();
66250b57cec5SDimitry Andric // Add the memory operand.
66260b57cec5SDimitry Andric if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
66270b57cec5SDimitry Andric int64_t Imm;
66280b57cec5SDimitry Andric if (IdVal->evaluateAsAbsolute(Imm))
66290b57cec5SDimitry Andric IdVal = MCConstantExpr::create(Imm, getContext());
66300b57cec5SDimitry Andric else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
66310b57cec5SDimitry Andric IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
66320b57cec5SDimitry Andric getContext());
66330b57cec5SDimitry Andric }
66340b57cec5SDimitry Andric
66350b57cec5SDimitry Andric Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
663606c3fb27SDimitry Andric return ParseStatus::Success;
66370b57cec5SDimitry Andric }
66380b57cec5SDimitry Andric
searchSymbolAlias(OperandVector & Operands)66390b57cec5SDimitry Andric bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
66400b57cec5SDimitry Andric MCAsmParser &Parser = getParser();
66410b57cec5SDimitry Andric MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
66420b57cec5SDimitry Andric if (!Sym)
66430b57cec5SDimitry Andric return false;
66440b57cec5SDimitry Andric
66450b57cec5SDimitry Andric SMLoc S = Parser.getTok().getLoc();
66460b57cec5SDimitry Andric if (Sym->isVariable()) {
66470b57cec5SDimitry Andric const MCExpr *Expr = Sym->getVariableValue();
66480b57cec5SDimitry Andric if (Expr->getKind() == MCExpr::SymbolRef) {
66490b57cec5SDimitry Andric const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
66500b57cec5SDimitry Andric StringRef DefSymbol = Ref->getSymbol().getName();
66515f757f3fSDimitry Andric if (DefSymbol.starts_with("$")) {
665206c3fb27SDimitry Andric ParseStatus Res =
66530b57cec5SDimitry Andric matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
665406c3fb27SDimitry Andric if (Res.isSuccess()) {
66550b57cec5SDimitry Andric Parser.Lex();
66560b57cec5SDimitry Andric return true;
66570b57cec5SDimitry Andric }
665806c3fb27SDimitry Andric if (Res.isFailure())
665906c3fb27SDimitry Andric llvm_unreachable("Should never fail");
66600b57cec5SDimitry Andric }
66610b57cec5SDimitry Andric }
66620b57cec5SDimitry Andric } else if (Sym->isUnset()) {
66630b57cec5SDimitry Andric // If symbol is unset, it might be created in the `parseSetAssignment`
66640b57cec5SDimitry Andric // routine as an alias for a numeric register name.
66650b57cec5SDimitry Andric // Lookup in the aliases list.
66660b57cec5SDimitry Andric auto Entry = RegisterSets.find(Sym->getName());
66670b57cec5SDimitry Andric if (Entry != RegisterSets.end()) {
666806c3fb27SDimitry Andric ParseStatus Res =
66690b57cec5SDimitry Andric matchAnyRegisterWithoutDollar(Operands, Entry->getValue(), S);
667006c3fb27SDimitry Andric if (Res.isSuccess()) {
66710b57cec5SDimitry Andric Parser.Lex();
66720b57cec5SDimitry Andric return true;
66730b57cec5SDimitry Andric }
66740b57cec5SDimitry Andric }
66750b57cec5SDimitry Andric }
66760b57cec5SDimitry Andric
66770b57cec5SDimitry Andric return false;
66780b57cec5SDimitry Andric }
66790b57cec5SDimitry Andric
matchAnyRegisterNameWithoutDollar(OperandVector & Operands,StringRef Identifier,SMLoc S)668006c3fb27SDimitry Andric ParseStatus MipsAsmParser::matchAnyRegisterNameWithoutDollar(
668106c3fb27SDimitry Andric OperandVector &Operands, StringRef Identifier, SMLoc S) {
66820b57cec5SDimitry Andric int Index = matchCPURegisterName(Identifier);
66830b57cec5SDimitry Andric if (Index != -1) {
66840b57cec5SDimitry Andric Operands.push_back(MipsOperand::createGPRReg(
66850b57cec5SDimitry Andric Index, Identifier, getContext().getRegisterInfo(), S,
66860b57cec5SDimitry Andric getLexer().getLoc(), *this));
668706c3fb27SDimitry Andric return ParseStatus::Success;
66880b57cec5SDimitry Andric }
66890b57cec5SDimitry Andric
66900b57cec5SDimitry Andric Index = matchHWRegsRegisterName(Identifier);
66910b57cec5SDimitry Andric if (Index != -1) {
66920b57cec5SDimitry Andric Operands.push_back(MipsOperand::createHWRegsReg(
66930b57cec5SDimitry Andric Index, Identifier, getContext().getRegisterInfo(), S,
66940b57cec5SDimitry Andric getLexer().getLoc(), *this));
669506c3fb27SDimitry Andric return ParseStatus::Success;
66960b57cec5SDimitry Andric }
66970b57cec5SDimitry Andric
66980b57cec5SDimitry Andric Index = matchFPURegisterName(Identifier);
66990b57cec5SDimitry Andric if (Index != -1) {
67000b57cec5SDimitry Andric Operands.push_back(MipsOperand::createFGRReg(
67010b57cec5SDimitry Andric Index, Identifier, getContext().getRegisterInfo(), S,
67020b57cec5SDimitry Andric getLexer().getLoc(), *this));
670306c3fb27SDimitry Andric return ParseStatus::Success;
67040b57cec5SDimitry Andric }
67050b57cec5SDimitry Andric
67060b57cec5SDimitry Andric Index = matchFCCRegisterName(Identifier);
67070b57cec5SDimitry Andric if (Index != -1) {
67080b57cec5SDimitry Andric Operands.push_back(MipsOperand::createFCCReg(
67090b57cec5SDimitry Andric Index, Identifier, getContext().getRegisterInfo(), S,
67100b57cec5SDimitry Andric getLexer().getLoc(), *this));
671106c3fb27SDimitry Andric return ParseStatus::Success;
67120b57cec5SDimitry Andric }
67130b57cec5SDimitry Andric
67140b57cec5SDimitry Andric Index = matchACRegisterName(Identifier);
67150b57cec5SDimitry Andric if (Index != -1) {
67160b57cec5SDimitry Andric Operands.push_back(MipsOperand::createACCReg(
67170b57cec5SDimitry Andric Index, Identifier, getContext().getRegisterInfo(), S,
67180b57cec5SDimitry Andric getLexer().getLoc(), *this));
671906c3fb27SDimitry Andric return ParseStatus::Success;
67200b57cec5SDimitry Andric }
67210b57cec5SDimitry Andric
67220b57cec5SDimitry Andric Index = matchMSA128RegisterName(Identifier);
67230b57cec5SDimitry Andric if (Index != -1) {
67240b57cec5SDimitry Andric Operands.push_back(MipsOperand::createMSA128Reg(
67250b57cec5SDimitry Andric Index, Identifier, getContext().getRegisterInfo(), S,
67260b57cec5SDimitry Andric getLexer().getLoc(), *this));
672706c3fb27SDimitry Andric return ParseStatus::Success;
67280b57cec5SDimitry Andric }
67290b57cec5SDimitry Andric
67300b57cec5SDimitry Andric Index = matchMSA128CtrlRegisterName(Identifier);
67310b57cec5SDimitry Andric if (Index != -1) {
67320b57cec5SDimitry Andric Operands.push_back(MipsOperand::createMSACtrlReg(
67330b57cec5SDimitry Andric Index, Identifier, getContext().getRegisterInfo(), S,
67340b57cec5SDimitry Andric getLexer().getLoc(), *this));
673506c3fb27SDimitry Andric return ParseStatus::Success;
67360b57cec5SDimitry Andric }
67370b57cec5SDimitry Andric
673806c3fb27SDimitry Andric return ParseStatus::NoMatch;
67390b57cec5SDimitry Andric }
67400b57cec5SDimitry Andric
674106c3fb27SDimitry Andric ParseStatus
matchAnyRegisterWithoutDollar(OperandVector & Operands,const AsmToken & Token,SMLoc S)67420b57cec5SDimitry Andric MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands,
67430b57cec5SDimitry Andric const AsmToken &Token, SMLoc S) {
67440b57cec5SDimitry Andric if (Token.is(AsmToken::Identifier)) {
67450b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << ".. identifier\n");
67460b57cec5SDimitry Andric StringRef Identifier = Token.getIdentifier();
674706c3fb27SDimitry Andric return matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
674806c3fb27SDimitry Andric }
674906c3fb27SDimitry Andric if (Token.is(AsmToken::Integer)) {
67500b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << ".. integer\n");
67510b57cec5SDimitry Andric int64_t RegNum = Token.getIntVal();
67520b57cec5SDimitry Andric if (RegNum < 0 || RegNum > 31) {
67530b57cec5SDimitry Andric // Show the error, but treat invalid register
67540b57cec5SDimitry Andric // number as a normal one to continue parsing
67550b57cec5SDimitry Andric // and catch other possible errors.
67560b57cec5SDimitry Andric Error(getLexer().getLoc(), "invalid register number");
67570b57cec5SDimitry Andric }
67580b57cec5SDimitry Andric Operands.push_back(MipsOperand::createNumericReg(
67590b57cec5SDimitry Andric RegNum, Token.getString(), getContext().getRegisterInfo(), S,
67600b57cec5SDimitry Andric Token.getLoc(), *this));
676106c3fb27SDimitry Andric return ParseStatus::Success;
67620b57cec5SDimitry Andric }
67630b57cec5SDimitry Andric
67640b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << Token.getKind() << "\n");
67650b57cec5SDimitry Andric
676606c3fb27SDimitry Andric return ParseStatus::NoMatch;
67670b57cec5SDimitry Andric }
67680b57cec5SDimitry Andric
676906c3fb27SDimitry Andric ParseStatus
matchAnyRegisterWithoutDollar(OperandVector & Operands,SMLoc S)67700b57cec5SDimitry Andric MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
67710b57cec5SDimitry Andric auto Token = getLexer().peekTok(false);
67720b57cec5SDimitry Andric return matchAnyRegisterWithoutDollar(Operands, Token, S);
67730b57cec5SDimitry Andric }
67740b57cec5SDimitry Andric
parseAnyRegister(OperandVector & Operands)677506c3fb27SDimitry Andric ParseStatus MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
67760b57cec5SDimitry Andric MCAsmParser &Parser = getParser();
67770b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "parseAnyRegister\n");
67780b57cec5SDimitry Andric
67790b57cec5SDimitry Andric auto Token = Parser.getTok();
67800b57cec5SDimitry Andric
67810b57cec5SDimitry Andric SMLoc S = Token.getLoc();
67820b57cec5SDimitry Andric
67830b57cec5SDimitry Andric if (Token.isNot(AsmToken::Dollar)) {
67840b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
67850b57cec5SDimitry Andric if (Token.is(AsmToken::Identifier)) {
67860b57cec5SDimitry Andric if (searchSymbolAlias(Operands))
678706c3fb27SDimitry Andric return ParseStatus::Success;
67880b57cec5SDimitry Andric }
67890b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
679006c3fb27SDimitry Andric return ParseStatus::NoMatch;
67910b57cec5SDimitry Andric }
67920b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << ".. $\n");
67930b57cec5SDimitry Andric
679406c3fb27SDimitry Andric ParseStatus Res = matchAnyRegisterWithoutDollar(Operands, S);
679506c3fb27SDimitry Andric if (Res.isSuccess()) {
67960b57cec5SDimitry Andric Parser.Lex(); // $
67970b57cec5SDimitry Andric Parser.Lex(); // identifier
67980b57cec5SDimitry Andric }
679906c3fb27SDimitry Andric return Res;
68000b57cec5SDimitry Andric }
68010b57cec5SDimitry Andric
parseJumpTarget(OperandVector & Operands)680206c3fb27SDimitry Andric ParseStatus MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
68030b57cec5SDimitry Andric MCAsmParser &Parser = getParser();
68040b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "parseJumpTarget\n");
68050b57cec5SDimitry Andric
68060b57cec5SDimitry Andric SMLoc S = getLexer().getLoc();
68070b57cec5SDimitry Andric
68080b57cec5SDimitry Andric // Registers are a valid target and have priority over symbols.
680906c3fb27SDimitry Andric ParseStatus Res = parseAnyRegister(Operands);
681006c3fb27SDimitry Andric if (!Res.isNoMatch())
681106c3fb27SDimitry Andric return Res;
68120b57cec5SDimitry Andric
68130b57cec5SDimitry Andric // Integers and expressions are acceptable
68140b57cec5SDimitry Andric const MCExpr *Expr = nullptr;
68150b57cec5SDimitry Andric if (Parser.parseExpression(Expr)) {
68160b57cec5SDimitry Andric // We have no way of knowing if a symbol was consumed so we must ParseFail
681706c3fb27SDimitry Andric return ParseStatus::Failure;
68180b57cec5SDimitry Andric }
68190b57cec5SDimitry Andric Operands.push_back(
68200b57cec5SDimitry Andric MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
682106c3fb27SDimitry Andric return ParseStatus::Success;
68220b57cec5SDimitry Andric }
68230b57cec5SDimitry Andric
parseInvNum(OperandVector & Operands)682406c3fb27SDimitry Andric ParseStatus MipsAsmParser::parseInvNum(OperandVector &Operands) {
68250b57cec5SDimitry Andric MCAsmParser &Parser = getParser();
68260b57cec5SDimitry Andric const MCExpr *IdVal;
68270b57cec5SDimitry Andric // If the first token is '$' we may have register operand. We have to reject
68280b57cec5SDimitry Andric // cases where it is not a register. Complicating the matter is that
68290b57cec5SDimitry Andric // register names are not reserved across all ABIs.
68300b57cec5SDimitry Andric // Peek past the dollar to see if it's a register name for this ABI.
68310b57cec5SDimitry Andric SMLoc S = Parser.getTok().getLoc();
68320b57cec5SDimitry Andric if (Parser.getTok().is(AsmToken::Dollar)) {
68330b57cec5SDimitry Andric return matchCPURegisterName(Parser.getLexer().peekTok().getString()) == -1
683406c3fb27SDimitry Andric ? ParseStatus::Failure
683506c3fb27SDimitry Andric : ParseStatus::NoMatch;
68360b57cec5SDimitry Andric }
68370b57cec5SDimitry Andric if (getParser().parseExpression(IdVal))
683806c3fb27SDimitry Andric return ParseStatus::Failure;
68390b57cec5SDimitry Andric const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
68400b57cec5SDimitry Andric if (!MCE)
684106c3fb27SDimitry Andric return ParseStatus::NoMatch;
68420b57cec5SDimitry Andric int64_t Val = MCE->getValue();
68430b57cec5SDimitry Andric SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
68440b57cec5SDimitry Andric Operands.push_back(MipsOperand::CreateImm(
68450b57cec5SDimitry Andric MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
684606c3fb27SDimitry Andric return ParseStatus::Success;
68470b57cec5SDimitry Andric }
68480b57cec5SDimitry Andric
parseRegisterList(OperandVector & Operands)684906c3fb27SDimitry Andric ParseStatus MipsAsmParser::parseRegisterList(OperandVector &Operands) {
68500b57cec5SDimitry Andric MCAsmParser &Parser = getParser();
68510b57cec5SDimitry Andric SmallVector<unsigned, 10> Regs;
68520b57cec5SDimitry Andric unsigned RegNo;
68530b57cec5SDimitry Andric unsigned PrevReg = Mips::NoRegister;
68540b57cec5SDimitry Andric bool RegRange = false;
68550b57cec5SDimitry Andric SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
68560b57cec5SDimitry Andric
68570b57cec5SDimitry Andric if (Parser.getTok().isNot(AsmToken::Dollar))
685806c3fb27SDimitry Andric return ParseStatus::Failure;
68590b57cec5SDimitry Andric
68600b57cec5SDimitry Andric SMLoc S = Parser.getTok().getLoc();
686106c3fb27SDimitry Andric while (parseAnyRegister(TmpOperands).isSuccess()) {
68620b57cec5SDimitry Andric SMLoc E = getLexer().getLoc();
68630b57cec5SDimitry Andric MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
68640b57cec5SDimitry Andric RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
68650b57cec5SDimitry Andric if (RegRange) {
68660b57cec5SDimitry Andric // Remove last register operand because registers from register range
68670b57cec5SDimitry Andric // should be inserted first.
68680b57cec5SDimitry Andric if ((isGP64bit() && RegNo == Mips::RA_64) ||
68690b57cec5SDimitry Andric (!isGP64bit() && RegNo == Mips::RA)) {
68700b57cec5SDimitry Andric Regs.push_back(RegNo);
68710b57cec5SDimitry Andric } else {
68720b57cec5SDimitry Andric unsigned TmpReg = PrevReg + 1;
68730b57cec5SDimitry Andric while (TmpReg <= RegNo) {
68740b57cec5SDimitry Andric if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) ||
68750b57cec5SDimitry Andric (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) &&
687606c3fb27SDimitry Andric isGP64bit()))
687706c3fb27SDimitry Andric return Error(E, "invalid register operand");
68780b57cec5SDimitry Andric
68790b57cec5SDimitry Andric PrevReg = TmpReg;
68800b57cec5SDimitry Andric Regs.push_back(TmpReg++);
68810b57cec5SDimitry Andric }
68820b57cec5SDimitry Andric }
68830b57cec5SDimitry Andric
68840b57cec5SDimitry Andric RegRange = false;
68850b57cec5SDimitry Andric } else {
68860b57cec5SDimitry Andric if ((PrevReg == Mips::NoRegister) &&
68870b57cec5SDimitry Andric ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) ||
688806c3fb27SDimitry Andric (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA))))
688906c3fb27SDimitry Andric return Error(E, "$16 or $31 expected");
689006c3fb27SDimitry Andric if (!(((RegNo == Mips::FP || RegNo == Mips::RA ||
68910b57cec5SDimitry Andric (RegNo >= Mips::S0 && RegNo <= Mips::S7)) &&
68920b57cec5SDimitry Andric !isGP64bit()) ||
68930b57cec5SDimitry Andric ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 ||
68940b57cec5SDimitry Andric (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) &&
689506c3fb27SDimitry Andric isGP64bit())))
689606c3fb27SDimitry Andric return Error(E, "invalid register operand");
689706c3fb27SDimitry Andric if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
68980b57cec5SDimitry Andric ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) ||
689906c3fb27SDimitry Andric (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 && isGP64bit())))
690006c3fb27SDimitry Andric return Error(E, "consecutive register numbers expected");
69010b57cec5SDimitry Andric
69020b57cec5SDimitry Andric Regs.push_back(RegNo);
69030b57cec5SDimitry Andric }
69040b57cec5SDimitry Andric
69050b57cec5SDimitry Andric if (Parser.getTok().is(AsmToken::Minus))
69060b57cec5SDimitry Andric RegRange = true;
69070b57cec5SDimitry Andric
69080b57cec5SDimitry Andric if (!Parser.getTok().isNot(AsmToken::Minus) &&
690906c3fb27SDimitry Andric !Parser.getTok().isNot(AsmToken::Comma))
691006c3fb27SDimitry Andric return Error(E, "',' or '-' expected");
69110b57cec5SDimitry Andric
69120b57cec5SDimitry Andric Lex(); // Consume comma or minus
69130b57cec5SDimitry Andric if (Parser.getTok().isNot(AsmToken::Dollar))
69140b57cec5SDimitry Andric break;
69150b57cec5SDimitry Andric
69160b57cec5SDimitry Andric PrevReg = RegNo;
69170b57cec5SDimitry Andric }
69180b57cec5SDimitry Andric
69190b57cec5SDimitry Andric SMLoc E = Parser.getTok().getLoc();
69200b57cec5SDimitry Andric Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
69210b57cec5SDimitry Andric parseMemOperand(Operands);
692206c3fb27SDimitry Andric return ParseStatus::Success;
69230b57cec5SDimitry Andric }
69240b57cec5SDimitry Andric
69250b57cec5SDimitry Andric /// Sometimes (i.e. load/stores) the operand may be followed immediately by
69260b57cec5SDimitry Andric /// either this.
69270b57cec5SDimitry Andric /// ::= '(', register, ')'
69280b57cec5SDimitry Andric /// handle it before we iterate so we don't get tripped up by the lack of
69290b57cec5SDimitry Andric /// a comma.
parseParenSuffix(StringRef Name,OperandVector & Operands)69300b57cec5SDimitry Andric bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
69310b57cec5SDimitry Andric MCAsmParser &Parser = getParser();
69320b57cec5SDimitry Andric if (getLexer().is(AsmToken::LParen)) {
69330b57cec5SDimitry Andric Operands.push_back(
69340b57cec5SDimitry Andric MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
69350b57cec5SDimitry Andric Parser.Lex();
69360b57cec5SDimitry Andric if (parseOperand(Operands, Name)) {
69370b57cec5SDimitry Andric SMLoc Loc = getLexer().getLoc();
69380b57cec5SDimitry Andric return Error(Loc, "unexpected token in argument list");
69390b57cec5SDimitry Andric }
69400b57cec5SDimitry Andric if (Parser.getTok().isNot(AsmToken::RParen)) {
69410b57cec5SDimitry Andric SMLoc Loc = getLexer().getLoc();
69420b57cec5SDimitry Andric return Error(Loc, "unexpected token, expected ')'");
69430b57cec5SDimitry Andric }
69440b57cec5SDimitry Andric Operands.push_back(
69450b57cec5SDimitry Andric MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
69460b57cec5SDimitry Andric Parser.Lex();
69470b57cec5SDimitry Andric }
69480b57cec5SDimitry Andric return false;
69490b57cec5SDimitry Andric }
69500b57cec5SDimitry Andric
69510b57cec5SDimitry Andric /// Sometimes (i.e. in MSA) the operand may be followed immediately by
69520b57cec5SDimitry Andric /// either one of these.
69530b57cec5SDimitry Andric /// ::= '[', register, ']'
69540b57cec5SDimitry Andric /// ::= '[', integer, ']'
69550b57cec5SDimitry Andric /// handle it before we iterate so we don't get tripped up by the lack of
69560b57cec5SDimitry Andric /// a comma.
parseBracketSuffix(StringRef Name,OperandVector & Operands)69570b57cec5SDimitry Andric bool MipsAsmParser::parseBracketSuffix(StringRef Name,
69580b57cec5SDimitry Andric OperandVector &Operands) {
69590b57cec5SDimitry Andric MCAsmParser &Parser = getParser();
69600b57cec5SDimitry Andric if (getLexer().is(AsmToken::LBrac)) {
69610b57cec5SDimitry Andric Operands.push_back(
69620b57cec5SDimitry Andric MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
69630b57cec5SDimitry Andric Parser.Lex();
69640b57cec5SDimitry Andric if (parseOperand(Operands, Name)) {
69650b57cec5SDimitry Andric SMLoc Loc = getLexer().getLoc();
69660b57cec5SDimitry Andric return Error(Loc, "unexpected token in argument list");
69670b57cec5SDimitry Andric }
69680b57cec5SDimitry Andric if (Parser.getTok().isNot(AsmToken::RBrac)) {
69690b57cec5SDimitry Andric SMLoc Loc = getLexer().getLoc();
69700b57cec5SDimitry Andric return Error(Loc, "unexpected token, expected ']'");
69710b57cec5SDimitry Andric }
69720b57cec5SDimitry Andric Operands.push_back(
69730b57cec5SDimitry Andric MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
69740b57cec5SDimitry Andric Parser.Lex();
69750b57cec5SDimitry Andric }
69760b57cec5SDimitry Andric return false;
69770b57cec5SDimitry Andric }
69780b57cec5SDimitry Andric
69790b57cec5SDimitry Andric static std::string MipsMnemonicSpellCheck(StringRef S, const FeatureBitset &FBS,
69800b57cec5SDimitry Andric unsigned VariantID = 0);
69810b57cec5SDimitry Andric
areEqualRegs(const MCParsedAsmOperand & Op1,const MCParsedAsmOperand & Op2) const6982bdd1243dSDimitry Andric bool MipsAsmParser::areEqualRegs(const MCParsedAsmOperand &Op1,
6983bdd1243dSDimitry Andric const MCParsedAsmOperand &Op2) const {
6984bdd1243dSDimitry Andric // This target-overriden function exists to maintain current behaviour for
6985bdd1243dSDimitry Andric // e.g.
6986bdd1243dSDimitry Andric // dahi $3, $3, 0x5678
6987bdd1243dSDimitry Andric // as tested in test/MC/Mips/mips64r6/valid.s.
6988bdd1243dSDimitry Andric // FIXME: Should this test actually fail with an error? If so, then remove
6989bdd1243dSDimitry Andric // this overloaded method.
6990bdd1243dSDimitry Andric if (!Op1.isReg() || !Op2.isReg())
6991bdd1243dSDimitry Andric return true;
6992bdd1243dSDimitry Andric return Op1.getReg() == Op2.getReg();
6993bdd1243dSDimitry Andric }
6994bdd1243dSDimitry Andric
ParseInstruction(ParseInstructionInfo & Info,StringRef Name,SMLoc NameLoc,OperandVector & Operands)69950b57cec5SDimitry Andric bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
69960b57cec5SDimitry Andric SMLoc NameLoc, OperandVector &Operands) {
69970b57cec5SDimitry Andric MCAsmParser &Parser = getParser();
69980b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "ParseInstruction\n");
69990b57cec5SDimitry Andric
70000b57cec5SDimitry Andric // We have reached first instruction, module directive are now forbidden.
70010b57cec5SDimitry Andric getTargetStreamer().forbidModuleDirective();
70020b57cec5SDimitry Andric
70030b57cec5SDimitry Andric // Check if we have valid mnemonic
70040b57cec5SDimitry Andric if (!mnemonicIsValid(Name, 0)) {
70050b57cec5SDimitry Andric FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());
70060b57cec5SDimitry Andric std::string Suggestion = MipsMnemonicSpellCheck(Name, FBS);
70070b57cec5SDimitry Andric return Error(NameLoc, "unknown instruction" + Suggestion);
70080b57cec5SDimitry Andric }
70090b57cec5SDimitry Andric // First operand in MCInst is instruction mnemonic.
70100b57cec5SDimitry Andric Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
70110b57cec5SDimitry Andric
70120b57cec5SDimitry Andric // Read the remaining operands.
70130b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) {
70140b57cec5SDimitry Andric // Read the first operand.
70150b57cec5SDimitry Andric if (parseOperand(Operands, Name)) {
70160b57cec5SDimitry Andric SMLoc Loc = getLexer().getLoc();
70170b57cec5SDimitry Andric return Error(Loc, "unexpected token in argument list");
70180b57cec5SDimitry Andric }
70190b57cec5SDimitry Andric if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
70200b57cec5SDimitry Andric return true;
70210b57cec5SDimitry Andric // AFAIK, parenthesis suffixes are never on the first operand
70220b57cec5SDimitry Andric
70230b57cec5SDimitry Andric while (getLexer().is(AsmToken::Comma)) {
70240b57cec5SDimitry Andric Parser.Lex(); // Eat the comma.
70250b57cec5SDimitry Andric // Parse and remember the operand.
70260b57cec5SDimitry Andric if (parseOperand(Operands, Name)) {
70270b57cec5SDimitry Andric SMLoc Loc = getLexer().getLoc();
70280b57cec5SDimitry Andric return Error(Loc, "unexpected token in argument list");
70290b57cec5SDimitry Andric }
70300b57cec5SDimitry Andric // Parse bracket and parenthesis suffixes before we iterate
70310b57cec5SDimitry Andric if (getLexer().is(AsmToken::LBrac)) {
70320b57cec5SDimitry Andric if (parseBracketSuffix(Name, Operands))
70330b57cec5SDimitry Andric return true;
70340b57cec5SDimitry Andric } else if (getLexer().is(AsmToken::LParen) &&
70350b57cec5SDimitry Andric parseParenSuffix(Name, Operands))
70360b57cec5SDimitry Andric return true;
70370b57cec5SDimitry Andric }
70380b57cec5SDimitry Andric }
70390b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) {
70400b57cec5SDimitry Andric SMLoc Loc = getLexer().getLoc();
70410b57cec5SDimitry Andric return Error(Loc, "unexpected token in argument list");
70420b57cec5SDimitry Andric }
70430b57cec5SDimitry Andric Parser.Lex(); // Consume the EndOfStatement.
70440b57cec5SDimitry Andric return false;
70450b57cec5SDimitry Andric }
70460b57cec5SDimitry Andric
70470b57cec5SDimitry Andric // FIXME: Given that these have the same name, these should both be
70480b57cec5SDimitry Andric // consistent on affecting the Parser.
reportParseError(const Twine & ErrorMsg)7049e8d8bef9SDimitry Andric bool MipsAsmParser::reportParseError(const Twine &ErrorMsg) {
70500b57cec5SDimitry Andric SMLoc Loc = getLexer().getLoc();
70510b57cec5SDimitry Andric return Error(Loc, ErrorMsg);
70520b57cec5SDimitry Andric }
70530b57cec5SDimitry Andric
reportParseError(SMLoc Loc,const Twine & ErrorMsg)7054e8d8bef9SDimitry Andric bool MipsAsmParser::reportParseError(SMLoc Loc, const Twine &ErrorMsg) {
70550b57cec5SDimitry Andric return Error(Loc, ErrorMsg);
70560b57cec5SDimitry Andric }
70570b57cec5SDimitry Andric
parseSetNoAtDirective()70580b57cec5SDimitry Andric bool MipsAsmParser::parseSetNoAtDirective() {
70590b57cec5SDimitry Andric MCAsmParser &Parser = getParser();
70600b57cec5SDimitry Andric // Line should look like: ".set noat".
70610b57cec5SDimitry Andric
70620b57cec5SDimitry Andric // Set the $at register to $0.
70630b57cec5SDimitry Andric AssemblerOptions.back()->setATRegIndex(0);
70640b57cec5SDimitry Andric
70650b57cec5SDimitry Andric Parser.Lex(); // Eat "noat".
70660b57cec5SDimitry Andric
70670b57cec5SDimitry Andric // If this is not the end of the statement, report an error.
70680b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) {
70690b57cec5SDimitry Andric reportParseError("unexpected token, expected end of statement");
70700b57cec5SDimitry Andric return false;
70710b57cec5SDimitry Andric }
70720b57cec5SDimitry Andric
70730b57cec5SDimitry Andric getTargetStreamer().emitDirectiveSetNoAt();
70740b57cec5SDimitry Andric Parser.Lex(); // Consume the EndOfStatement.
70750b57cec5SDimitry Andric return false;
70760b57cec5SDimitry Andric }
70770b57cec5SDimitry Andric
parseSetAtDirective()70780b57cec5SDimitry Andric bool MipsAsmParser::parseSetAtDirective() {
70790b57cec5SDimitry Andric // Line can be: ".set at", which sets $at to $1
70800b57cec5SDimitry Andric // or ".set at=$reg", which sets $at to $reg.
70810b57cec5SDimitry Andric MCAsmParser &Parser = getParser();
70820b57cec5SDimitry Andric Parser.Lex(); // Eat "at".
70830b57cec5SDimitry Andric
70840b57cec5SDimitry Andric if (getLexer().is(AsmToken::EndOfStatement)) {
70850b57cec5SDimitry Andric // No register was specified, so we set $at to $1.
70860b57cec5SDimitry Andric AssemblerOptions.back()->setATRegIndex(1);
70870b57cec5SDimitry Andric
70880b57cec5SDimitry Andric getTargetStreamer().emitDirectiveSetAt();
70890b57cec5SDimitry Andric Parser.Lex(); // Consume the EndOfStatement.
70900b57cec5SDimitry Andric return false;
70910b57cec5SDimitry Andric }
70920b57cec5SDimitry Andric
70930b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::Equal)) {
70940b57cec5SDimitry Andric reportParseError("unexpected token, expected equals sign");
70950b57cec5SDimitry Andric return false;
70960b57cec5SDimitry Andric }
70970b57cec5SDimitry Andric Parser.Lex(); // Eat "=".
70980b57cec5SDimitry Andric
70990b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::Dollar)) {
71000b57cec5SDimitry Andric if (getLexer().is(AsmToken::EndOfStatement)) {
71010b57cec5SDimitry Andric reportParseError("no register specified");
71020b57cec5SDimitry Andric return false;
71030b57cec5SDimitry Andric } else {
71040b57cec5SDimitry Andric reportParseError("unexpected token, expected dollar sign '$'");
71050b57cec5SDimitry Andric return false;
71060b57cec5SDimitry Andric }
71070b57cec5SDimitry Andric }
71080b57cec5SDimitry Andric Parser.Lex(); // Eat "$".
71090b57cec5SDimitry Andric
71100b57cec5SDimitry Andric // Find out what "reg" is.
71110b57cec5SDimitry Andric unsigned AtRegNo;
71120b57cec5SDimitry Andric const AsmToken &Reg = Parser.getTok();
71130b57cec5SDimitry Andric if (Reg.is(AsmToken::Identifier)) {
71140b57cec5SDimitry Andric AtRegNo = matchCPURegisterName(Reg.getIdentifier());
71150b57cec5SDimitry Andric } else if (Reg.is(AsmToken::Integer)) {
71160b57cec5SDimitry Andric AtRegNo = Reg.getIntVal();
71170b57cec5SDimitry Andric } else {
71180b57cec5SDimitry Andric reportParseError("unexpected token, expected identifier or integer");
71190b57cec5SDimitry Andric return false;
71200b57cec5SDimitry Andric }
71210b57cec5SDimitry Andric
71220b57cec5SDimitry Andric // Check if $reg is a valid register. If it is, set $at to $reg.
71230b57cec5SDimitry Andric if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
71240b57cec5SDimitry Andric reportParseError("invalid register");
71250b57cec5SDimitry Andric return false;
71260b57cec5SDimitry Andric }
71270b57cec5SDimitry Andric Parser.Lex(); // Eat "reg".
71280b57cec5SDimitry Andric
71290b57cec5SDimitry Andric // If this is not the end of the statement, report an error.
71300b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) {
71310b57cec5SDimitry Andric reportParseError("unexpected token, expected end of statement");
71320b57cec5SDimitry Andric return false;
71330b57cec5SDimitry Andric }
71340b57cec5SDimitry Andric
71350b57cec5SDimitry Andric getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
71360b57cec5SDimitry Andric
71370b57cec5SDimitry Andric Parser.Lex(); // Consume the EndOfStatement.
71380b57cec5SDimitry Andric return false;
71390b57cec5SDimitry Andric }
71400b57cec5SDimitry Andric
parseSetReorderDirective()71410b57cec5SDimitry Andric bool MipsAsmParser::parseSetReorderDirective() {
71420b57cec5SDimitry Andric MCAsmParser &Parser = getParser();
71430b57cec5SDimitry Andric Parser.Lex();
71440b57cec5SDimitry Andric // If this is not the end of the statement, report an error.
71450b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) {
71460b57cec5SDimitry Andric reportParseError("unexpected token, expected end of statement");
71470b57cec5SDimitry Andric return false;
71480b57cec5SDimitry Andric }
71490b57cec5SDimitry Andric AssemblerOptions.back()->setReorder();
71500b57cec5SDimitry Andric getTargetStreamer().emitDirectiveSetReorder();
71510b57cec5SDimitry Andric Parser.Lex(); // Consume the EndOfStatement.
71520b57cec5SDimitry Andric return false;
71530b57cec5SDimitry Andric }
71540b57cec5SDimitry Andric
parseSetNoReorderDirective()71550b57cec5SDimitry Andric bool MipsAsmParser::parseSetNoReorderDirective() {
71560b57cec5SDimitry Andric MCAsmParser &Parser = getParser();
71570b57cec5SDimitry Andric Parser.Lex();
71580b57cec5SDimitry Andric // If this is not the end of the statement, report an error.
71590b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) {
71600b57cec5SDimitry Andric reportParseError("unexpected token, expected end of statement");
71610b57cec5SDimitry Andric return false;
71620b57cec5SDimitry Andric }
71630b57cec5SDimitry Andric AssemblerOptions.back()->setNoReorder();
71640b57cec5SDimitry Andric getTargetStreamer().emitDirectiveSetNoReorder();
71650b57cec5SDimitry Andric Parser.Lex(); // Consume the EndOfStatement.
71660b57cec5SDimitry Andric return false;
71670b57cec5SDimitry Andric }
71680b57cec5SDimitry Andric
parseSetMacroDirective()71690b57cec5SDimitry Andric bool MipsAsmParser::parseSetMacroDirective() {
71700b57cec5SDimitry Andric MCAsmParser &Parser = getParser();
71710b57cec5SDimitry Andric Parser.Lex();
71720b57cec5SDimitry Andric // If this is not the end of the statement, report an error.
71730b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) {
71740b57cec5SDimitry Andric reportParseError("unexpected token, expected end of statement");
71750b57cec5SDimitry Andric return false;
71760b57cec5SDimitry Andric }
71770b57cec5SDimitry Andric AssemblerOptions.back()->setMacro();
71780b57cec5SDimitry Andric getTargetStreamer().emitDirectiveSetMacro();
71790b57cec5SDimitry Andric Parser.Lex(); // Consume the EndOfStatement.
71800b57cec5SDimitry Andric return false;
71810b57cec5SDimitry Andric }
71820b57cec5SDimitry Andric
parseSetNoMacroDirective()71830b57cec5SDimitry Andric bool MipsAsmParser::parseSetNoMacroDirective() {
71840b57cec5SDimitry Andric MCAsmParser &Parser = getParser();
71850b57cec5SDimitry Andric Parser.Lex();
71860b57cec5SDimitry Andric // If this is not the end of the statement, report an error.
71870b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) {
71880b57cec5SDimitry Andric reportParseError("unexpected token, expected end of statement");
71890b57cec5SDimitry Andric return false;
71900b57cec5SDimitry Andric }
71910b57cec5SDimitry Andric if (AssemblerOptions.back()->isReorder()) {
71920b57cec5SDimitry Andric reportParseError("`noreorder' must be set before `nomacro'");
71930b57cec5SDimitry Andric return false;
71940b57cec5SDimitry Andric }
71950b57cec5SDimitry Andric AssemblerOptions.back()->setNoMacro();
71960b57cec5SDimitry Andric getTargetStreamer().emitDirectiveSetNoMacro();
71970b57cec5SDimitry Andric Parser.Lex(); // Consume the EndOfStatement.
71980b57cec5SDimitry Andric return false;
71990b57cec5SDimitry Andric }
72000b57cec5SDimitry Andric
parseSetMsaDirective()72010b57cec5SDimitry Andric bool MipsAsmParser::parseSetMsaDirective() {
72020b57cec5SDimitry Andric MCAsmParser &Parser = getParser();
72030b57cec5SDimitry Andric Parser.Lex();
72040b57cec5SDimitry Andric
72050b57cec5SDimitry Andric // If this is not the end of the statement, report an error.
72060b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement))
72070b57cec5SDimitry Andric return reportParseError("unexpected token, expected end of statement");
72080b57cec5SDimitry Andric
72090b57cec5SDimitry Andric setFeatureBits(Mips::FeatureMSA, "msa");
72100b57cec5SDimitry Andric getTargetStreamer().emitDirectiveSetMsa();
72110b57cec5SDimitry Andric return false;
72120b57cec5SDimitry Andric }
72130b57cec5SDimitry Andric
parseSetNoMsaDirective()72140b57cec5SDimitry Andric bool MipsAsmParser::parseSetNoMsaDirective() {
72150b57cec5SDimitry Andric MCAsmParser &Parser = getParser();
72160b57cec5SDimitry Andric Parser.Lex();
72170b57cec5SDimitry Andric
72180b57cec5SDimitry Andric // If this is not the end of the statement, report an error.
72190b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement))
72200b57cec5SDimitry Andric return reportParseError("unexpected token, expected end of statement");
72210b57cec5SDimitry Andric
72220b57cec5SDimitry Andric clearFeatureBits(Mips::FeatureMSA, "msa");
72230b57cec5SDimitry Andric getTargetStreamer().emitDirectiveSetNoMsa();
72240b57cec5SDimitry Andric return false;
72250b57cec5SDimitry Andric }
72260b57cec5SDimitry Andric
parseSetNoDspDirective()72270b57cec5SDimitry Andric bool MipsAsmParser::parseSetNoDspDirective() {
72280b57cec5SDimitry Andric MCAsmParser &Parser = getParser();
72290b57cec5SDimitry Andric Parser.Lex(); // Eat "nodsp".
72300b57cec5SDimitry Andric
72310b57cec5SDimitry Andric // If this is not the end of the statement, report an error.
72320b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) {
72330b57cec5SDimitry Andric reportParseError("unexpected token, expected end of statement");
72340b57cec5SDimitry Andric return false;
72350b57cec5SDimitry Andric }
72360b57cec5SDimitry Andric
72370b57cec5SDimitry Andric clearFeatureBits(Mips::FeatureDSP, "dsp");
72380b57cec5SDimitry Andric getTargetStreamer().emitDirectiveSetNoDsp();
72390b57cec5SDimitry Andric return false;
72400b57cec5SDimitry Andric }
72410b57cec5SDimitry Andric
parseSetNoMips3DDirective()72425ffd83dbSDimitry Andric bool MipsAsmParser::parseSetNoMips3DDirective() {
72435ffd83dbSDimitry Andric MCAsmParser &Parser = getParser();
72445ffd83dbSDimitry Andric Parser.Lex(); // Eat "nomips3d".
72455ffd83dbSDimitry Andric
72465ffd83dbSDimitry Andric // If this is not the end of the statement, report an error.
72475ffd83dbSDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) {
72485ffd83dbSDimitry Andric reportParseError("unexpected token, expected end of statement");
72495ffd83dbSDimitry Andric return false;
72505ffd83dbSDimitry Andric }
72515ffd83dbSDimitry Andric
72525ffd83dbSDimitry Andric clearFeatureBits(Mips::FeatureMips3D, "mips3d");
72535ffd83dbSDimitry Andric getTargetStreamer().emitDirectiveSetNoMips3D();
72545ffd83dbSDimitry Andric return false;
72555ffd83dbSDimitry Andric }
72565ffd83dbSDimitry Andric
parseSetMips16Directive()72570b57cec5SDimitry Andric bool MipsAsmParser::parseSetMips16Directive() {
72580b57cec5SDimitry Andric MCAsmParser &Parser = getParser();
72590b57cec5SDimitry Andric Parser.Lex(); // Eat "mips16".
72600b57cec5SDimitry Andric
72610b57cec5SDimitry Andric // If this is not the end of the statement, report an error.
72620b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) {
72630b57cec5SDimitry Andric reportParseError("unexpected token, expected end of statement");
72640b57cec5SDimitry Andric return false;
72650b57cec5SDimitry Andric }
72660b57cec5SDimitry Andric
72670b57cec5SDimitry Andric setFeatureBits(Mips::FeatureMips16, "mips16");
72680b57cec5SDimitry Andric getTargetStreamer().emitDirectiveSetMips16();
72690b57cec5SDimitry Andric Parser.Lex(); // Consume the EndOfStatement.
72700b57cec5SDimitry Andric return false;
72710b57cec5SDimitry Andric }
72720b57cec5SDimitry Andric
parseSetNoMips16Directive()72730b57cec5SDimitry Andric bool MipsAsmParser::parseSetNoMips16Directive() {
72740b57cec5SDimitry Andric MCAsmParser &Parser = getParser();
72750b57cec5SDimitry Andric Parser.Lex(); // Eat "nomips16".
72760b57cec5SDimitry Andric
72770b57cec5SDimitry Andric // If this is not the end of the statement, report an error.
72780b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) {
72790b57cec5SDimitry Andric reportParseError("unexpected token, expected end of statement");
72800b57cec5SDimitry Andric return false;
72810b57cec5SDimitry Andric }
72820b57cec5SDimitry Andric
72830b57cec5SDimitry Andric clearFeatureBits(Mips::FeatureMips16, "mips16");
72840b57cec5SDimitry Andric getTargetStreamer().emitDirectiveSetNoMips16();
72850b57cec5SDimitry Andric Parser.Lex(); // Consume the EndOfStatement.
72860b57cec5SDimitry Andric return false;
72870b57cec5SDimitry Andric }
72880b57cec5SDimitry Andric
parseSetFpDirective()72890b57cec5SDimitry Andric bool MipsAsmParser::parseSetFpDirective() {
72900b57cec5SDimitry Andric MCAsmParser &Parser = getParser();
72910b57cec5SDimitry Andric MipsABIFlagsSection::FpABIKind FpAbiVal;
72920b57cec5SDimitry Andric // Line can be: .set fp=32
72930b57cec5SDimitry Andric // .set fp=xx
72940b57cec5SDimitry Andric // .set fp=64
72950b57cec5SDimitry Andric Parser.Lex(); // Eat fp token
72960b57cec5SDimitry Andric AsmToken Tok = Parser.getTok();
72970b57cec5SDimitry Andric if (Tok.isNot(AsmToken::Equal)) {
72980b57cec5SDimitry Andric reportParseError("unexpected token, expected equals sign '='");
72990b57cec5SDimitry Andric return false;
73000b57cec5SDimitry Andric }
73010b57cec5SDimitry Andric Parser.Lex(); // Eat '=' token.
73020b57cec5SDimitry Andric Tok = Parser.getTok();
73030b57cec5SDimitry Andric
73040b57cec5SDimitry Andric if (!parseFpABIValue(FpAbiVal, ".set"))
73050b57cec5SDimitry Andric return false;
73060b57cec5SDimitry Andric
73070b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) {
73080b57cec5SDimitry Andric reportParseError("unexpected token, expected end of statement");
73090b57cec5SDimitry Andric return false;
73100b57cec5SDimitry Andric }
73110b57cec5SDimitry Andric getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
73120b57cec5SDimitry Andric Parser.Lex(); // Consume the EndOfStatement.
73130b57cec5SDimitry Andric return false;
73140b57cec5SDimitry Andric }
73150b57cec5SDimitry Andric
parseSetOddSPRegDirective()73160b57cec5SDimitry Andric bool MipsAsmParser::parseSetOddSPRegDirective() {
73170b57cec5SDimitry Andric MCAsmParser &Parser = getParser();
73180b57cec5SDimitry Andric
73190b57cec5SDimitry Andric Parser.Lex(); // Eat "oddspreg".
73200b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) {
73210b57cec5SDimitry Andric reportParseError("unexpected token, expected end of statement");
73220b57cec5SDimitry Andric return false;
73230b57cec5SDimitry Andric }
73240b57cec5SDimitry Andric
73250b57cec5SDimitry Andric clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
73260b57cec5SDimitry Andric getTargetStreamer().emitDirectiveSetOddSPReg();
73270b57cec5SDimitry Andric return false;
73280b57cec5SDimitry Andric }
73290b57cec5SDimitry Andric
parseSetNoOddSPRegDirective()73300b57cec5SDimitry Andric bool MipsAsmParser::parseSetNoOddSPRegDirective() {
73310b57cec5SDimitry Andric MCAsmParser &Parser = getParser();
73320b57cec5SDimitry Andric
73330b57cec5SDimitry Andric Parser.Lex(); // Eat "nooddspreg".
73340b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) {
73350b57cec5SDimitry Andric reportParseError("unexpected token, expected end of statement");
73360b57cec5SDimitry Andric return false;
73370b57cec5SDimitry Andric }
73380b57cec5SDimitry Andric
73390b57cec5SDimitry Andric setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
73400b57cec5SDimitry Andric getTargetStreamer().emitDirectiveSetNoOddSPReg();
73410b57cec5SDimitry Andric return false;
73420b57cec5SDimitry Andric }
73430b57cec5SDimitry Andric
parseSetMtDirective()73440b57cec5SDimitry Andric bool MipsAsmParser::parseSetMtDirective() {
73450b57cec5SDimitry Andric MCAsmParser &Parser = getParser();
73460b57cec5SDimitry Andric Parser.Lex(); // Eat "mt".
73470b57cec5SDimitry Andric
73480b57cec5SDimitry Andric // If this is not the end of the statement, report an error.
73490b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) {
73500b57cec5SDimitry Andric reportParseError("unexpected token, expected end of statement");
73510b57cec5SDimitry Andric return false;
73520b57cec5SDimitry Andric }
73530b57cec5SDimitry Andric
73540b57cec5SDimitry Andric setFeatureBits(Mips::FeatureMT, "mt");
73550b57cec5SDimitry Andric getTargetStreamer().emitDirectiveSetMt();
73560b57cec5SDimitry Andric Parser.Lex(); // Consume the EndOfStatement.
73570b57cec5SDimitry Andric return false;
73580b57cec5SDimitry Andric }
73590b57cec5SDimitry Andric
parseSetNoMtDirective()73600b57cec5SDimitry Andric bool MipsAsmParser::parseSetNoMtDirective() {
73610b57cec5SDimitry Andric MCAsmParser &Parser = getParser();
73620b57cec5SDimitry Andric Parser.Lex(); // Eat "nomt".
73630b57cec5SDimitry Andric
73640b57cec5SDimitry Andric // If this is not the end of the statement, report an error.
73650b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) {
73660b57cec5SDimitry Andric reportParseError("unexpected token, expected end of statement");
73670b57cec5SDimitry Andric return false;
73680b57cec5SDimitry Andric }
73690b57cec5SDimitry Andric
73700b57cec5SDimitry Andric clearFeatureBits(Mips::FeatureMT, "mt");
73710b57cec5SDimitry Andric
73720b57cec5SDimitry Andric getTargetStreamer().emitDirectiveSetNoMt();
73730b57cec5SDimitry Andric Parser.Lex(); // Consume the EndOfStatement.
73740b57cec5SDimitry Andric return false;
73750b57cec5SDimitry Andric }
73760b57cec5SDimitry Andric
parseSetNoCRCDirective()73770b57cec5SDimitry Andric bool MipsAsmParser::parseSetNoCRCDirective() {
73780b57cec5SDimitry Andric MCAsmParser &Parser = getParser();
73790b57cec5SDimitry Andric Parser.Lex(); // Eat "nocrc".
73800b57cec5SDimitry Andric
73810b57cec5SDimitry Andric // If this is not the end of the statement, report an error.
73820b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) {
73830b57cec5SDimitry Andric reportParseError("unexpected token, expected end of statement");
73840b57cec5SDimitry Andric return false;
73850b57cec5SDimitry Andric }
73860b57cec5SDimitry Andric
73870b57cec5SDimitry Andric clearFeatureBits(Mips::FeatureCRC, "crc");
73880b57cec5SDimitry Andric
73890b57cec5SDimitry Andric getTargetStreamer().emitDirectiveSetNoCRC();
73900b57cec5SDimitry Andric Parser.Lex(); // Consume the EndOfStatement.
73910b57cec5SDimitry Andric return false;
73920b57cec5SDimitry Andric }
73930b57cec5SDimitry Andric
parseSetNoVirtDirective()73940b57cec5SDimitry Andric bool MipsAsmParser::parseSetNoVirtDirective() {
73950b57cec5SDimitry Andric MCAsmParser &Parser = getParser();
73960b57cec5SDimitry Andric Parser.Lex(); // Eat "novirt".
73970b57cec5SDimitry Andric
73980b57cec5SDimitry Andric // If this is not the end of the statement, report an error.
73990b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) {
74000b57cec5SDimitry Andric reportParseError("unexpected token, expected end of statement");
74010b57cec5SDimitry Andric return false;
74020b57cec5SDimitry Andric }
74030b57cec5SDimitry Andric
74040b57cec5SDimitry Andric clearFeatureBits(Mips::FeatureVirt, "virt");
74050b57cec5SDimitry Andric
74060b57cec5SDimitry Andric getTargetStreamer().emitDirectiveSetNoVirt();
74070b57cec5SDimitry Andric Parser.Lex(); // Consume the EndOfStatement.
74080b57cec5SDimitry Andric return false;
74090b57cec5SDimitry Andric }
74100b57cec5SDimitry Andric
parseSetNoGINVDirective()74110b57cec5SDimitry Andric bool MipsAsmParser::parseSetNoGINVDirective() {
74120b57cec5SDimitry Andric MCAsmParser &Parser = getParser();
74130b57cec5SDimitry Andric Parser.Lex(); // Eat "noginv".
74140b57cec5SDimitry Andric
74150b57cec5SDimitry Andric // If this is not the end of the statement, report an error.
74160b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) {
74170b57cec5SDimitry Andric reportParseError("unexpected token, expected end of statement");
74180b57cec5SDimitry Andric return false;
74190b57cec5SDimitry Andric }
74200b57cec5SDimitry Andric
74210b57cec5SDimitry Andric clearFeatureBits(Mips::FeatureGINV, "ginv");
74220b57cec5SDimitry Andric
74230b57cec5SDimitry Andric getTargetStreamer().emitDirectiveSetNoGINV();
74240b57cec5SDimitry Andric Parser.Lex(); // Consume the EndOfStatement.
74250b57cec5SDimitry Andric return false;
74260b57cec5SDimitry Andric }
74270b57cec5SDimitry Andric
parseSetPopDirective()74280b57cec5SDimitry Andric bool MipsAsmParser::parseSetPopDirective() {
74290b57cec5SDimitry Andric MCAsmParser &Parser = getParser();
74300b57cec5SDimitry Andric SMLoc Loc = getLexer().getLoc();
74310b57cec5SDimitry Andric
74320b57cec5SDimitry Andric Parser.Lex();
74330b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement))
74340b57cec5SDimitry Andric return reportParseError("unexpected token, expected end of statement");
74350b57cec5SDimitry Andric
74360b57cec5SDimitry Andric // Always keep an element on the options "stack" to prevent the user
74370b57cec5SDimitry Andric // from changing the initial options. This is how we remember them.
74380b57cec5SDimitry Andric if (AssemblerOptions.size() == 2)
74390b57cec5SDimitry Andric return reportParseError(Loc, ".set pop with no .set push");
74400b57cec5SDimitry Andric
74410b57cec5SDimitry Andric MCSubtargetInfo &STI = copySTI();
74420b57cec5SDimitry Andric AssemblerOptions.pop_back();
74430b57cec5SDimitry Andric setAvailableFeatures(
74440b57cec5SDimitry Andric ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
74450b57cec5SDimitry Andric STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
74460b57cec5SDimitry Andric
74470b57cec5SDimitry Andric getTargetStreamer().emitDirectiveSetPop();
74480b57cec5SDimitry Andric return false;
74490b57cec5SDimitry Andric }
74500b57cec5SDimitry Andric
parseSetPushDirective()74510b57cec5SDimitry Andric bool MipsAsmParser::parseSetPushDirective() {
74520b57cec5SDimitry Andric MCAsmParser &Parser = getParser();
74530b57cec5SDimitry Andric Parser.Lex();
74540b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement))
74550b57cec5SDimitry Andric return reportParseError("unexpected token, expected end of statement");
74560b57cec5SDimitry Andric
74570b57cec5SDimitry Andric // Create a copy of the current assembler options environment and push it.
74580b57cec5SDimitry Andric AssemblerOptions.push_back(
74598bcb0991SDimitry Andric std::make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
74600b57cec5SDimitry Andric
74610b57cec5SDimitry Andric getTargetStreamer().emitDirectiveSetPush();
74620b57cec5SDimitry Andric return false;
74630b57cec5SDimitry Andric }
74640b57cec5SDimitry Andric
parseSetSoftFloatDirective()74650b57cec5SDimitry Andric bool MipsAsmParser::parseSetSoftFloatDirective() {
74660b57cec5SDimitry Andric MCAsmParser &Parser = getParser();
74670b57cec5SDimitry Andric Parser.Lex();
74680b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement))
74690b57cec5SDimitry Andric return reportParseError("unexpected token, expected end of statement");
74700b57cec5SDimitry Andric
74710b57cec5SDimitry Andric setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
74720b57cec5SDimitry Andric getTargetStreamer().emitDirectiveSetSoftFloat();
74730b57cec5SDimitry Andric return false;
74740b57cec5SDimitry Andric }
74750b57cec5SDimitry Andric
parseSetHardFloatDirective()74760b57cec5SDimitry Andric bool MipsAsmParser::parseSetHardFloatDirective() {
74770b57cec5SDimitry Andric MCAsmParser &Parser = getParser();
74780b57cec5SDimitry Andric Parser.Lex();
74790b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement))
74800b57cec5SDimitry Andric return reportParseError("unexpected token, expected end of statement");
74810b57cec5SDimitry Andric
74820b57cec5SDimitry Andric clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
74830b57cec5SDimitry Andric getTargetStreamer().emitDirectiveSetHardFloat();
74840b57cec5SDimitry Andric return false;
74850b57cec5SDimitry Andric }
74860b57cec5SDimitry Andric
parseSetAssignment()74870b57cec5SDimitry Andric bool MipsAsmParser::parseSetAssignment() {
74880b57cec5SDimitry Andric StringRef Name;
74890b57cec5SDimitry Andric MCAsmParser &Parser = getParser();
74900b57cec5SDimitry Andric
74910b57cec5SDimitry Andric if (Parser.parseIdentifier(Name))
74920b57cec5SDimitry Andric return reportParseError("expected identifier after .set");
74930b57cec5SDimitry Andric
74940b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::Comma))
74950b57cec5SDimitry Andric return reportParseError("unexpected token, expected comma");
74960b57cec5SDimitry Andric Lex(); // Eat comma
74970b57cec5SDimitry Andric
74980b57cec5SDimitry Andric if (getLexer().is(AsmToken::Dollar) &&
74990b57cec5SDimitry Andric getLexer().peekTok().is(AsmToken::Integer)) {
75000b57cec5SDimitry Andric // Parse assignment of a numeric register:
75010b57cec5SDimitry Andric // .set r1,$1
75020b57cec5SDimitry Andric Parser.Lex(); // Eat $.
75030b57cec5SDimitry Andric RegisterSets[Name] = Parser.getTok();
75040b57cec5SDimitry Andric Parser.Lex(); // Eat identifier.
75050b57cec5SDimitry Andric getContext().getOrCreateSymbol(Name);
75060b57cec5SDimitry Andric return false;
75070b57cec5SDimitry Andric }
75080b57cec5SDimitry Andric
75090b57cec5SDimitry Andric MCSymbol *Sym;
75100b57cec5SDimitry Andric const MCExpr *Value;
75110b57cec5SDimitry Andric if (MCParserUtils::parseAssignmentExpression(Name, /* allow_redef */ true,
75120b57cec5SDimitry Andric Parser, Sym, Value))
75130b57cec5SDimitry Andric return true;
75140b57cec5SDimitry Andric Sym->setVariableValue(Value);
75150b57cec5SDimitry Andric
75160b57cec5SDimitry Andric return false;
75170b57cec5SDimitry Andric }
75180b57cec5SDimitry Andric
parseSetMips0Directive()75190b57cec5SDimitry Andric bool MipsAsmParser::parseSetMips0Directive() {
75200b57cec5SDimitry Andric MCAsmParser &Parser = getParser();
75210b57cec5SDimitry Andric Parser.Lex();
75220b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement))
75230b57cec5SDimitry Andric return reportParseError("unexpected token, expected end of statement");
75240b57cec5SDimitry Andric
75250b57cec5SDimitry Andric // Reset assembler options to their initial values.
75260b57cec5SDimitry Andric MCSubtargetInfo &STI = copySTI();
75270b57cec5SDimitry Andric setAvailableFeatures(
75280b57cec5SDimitry Andric ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
75290b57cec5SDimitry Andric STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
75300b57cec5SDimitry Andric AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
75310b57cec5SDimitry Andric
75320b57cec5SDimitry Andric getTargetStreamer().emitDirectiveSetMips0();
75330b57cec5SDimitry Andric return false;
75340b57cec5SDimitry Andric }
75350b57cec5SDimitry Andric
parseSetArchDirective()75360b57cec5SDimitry Andric bool MipsAsmParser::parseSetArchDirective() {
75370b57cec5SDimitry Andric MCAsmParser &Parser = getParser();
75380b57cec5SDimitry Andric Parser.Lex();
75390b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::Equal))
75400b57cec5SDimitry Andric return reportParseError("unexpected token, expected equals sign");
75410b57cec5SDimitry Andric
75420b57cec5SDimitry Andric Parser.Lex();
75430b57cec5SDimitry Andric StringRef Arch = getParser().parseStringToEndOfStatement().trim();
75440b57cec5SDimitry Andric if (Arch.empty())
75450b57cec5SDimitry Andric return reportParseError("expected arch identifier");
75460b57cec5SDimitry Andric
75470b57cec5SDimitry Andric StringRef ArchFeatureName =
75480b57cec5SDimitry Andric StringSwitch<StringRef>(Arch)
75490b57cec5SDimitry Andric .Case("mips1", "mips1")
75500b57cec5SDimitry Andric .Case("mips2", "mips2")
75510b57cec5SDimitry Andric .Case("mips3", "mips3")
75520b57cec5SDimitry Andric .Case("mips4", "mips4")
75530b57cec5SDimitry Andric .Case("mips5", "mips5")
75540b57cec5SDimitry Andric .Case("mips32", "mips32")
75550b57cec5SDimitry Andric .Case("mips32r2", "mips32r2")
75560b57cec5SDimitry Andric .Case("mips32r3", "mips32r3")
75570b57cec5SDimitry Andric .Case("mips32r5", "mips32r5")
75580b57cec5SDimitry Andric .Case("mips32r6", "mips32r6")
75590b57cec5SDimitry Andric .Case("mips64", "mips64")
75600b57cec5SDimitry Andric .Case("mips64r2", "mips64r2")
75610b57cec5SDimitry Andric .Case("mips64r3", "mips64r3")
75620b57cec5SDimitry Andric .Case("mips64r5", "mips64r5")
75630b57cec5SDimitry Andric .Case("mips64r6", "mips64r6")
75640b57cec5SDimitry Andric .Case("octeon", "cnmips")
75650b57cec5SDimitry Andric .Case("octeon+", "cnmipsp")
75660b57cec5SDimitry Andric .Case("r4000", "mips3") // This is an implementation of Mips3.
75670b57cec5SDimitry Andric .Default("");
75680b57cec5SDimitry Andric
75690b57cec5SDimitry Andric if (ArchFeatureName.empty())
75700b57cec5SDimitry Andric return reportParseError("unsupported architecture");
75710b57cec5SDimitry Andric
75720b57cec5SDimitry Andric if (ArchFeatureName == "mips64r6" && inMicroMipsMode())
75730b57cec5SDimitry Andric return reportParseError("mips64r6 does not support microMIPS");
75740b57cec5SDimitry Andric
75750b57cec5SDimitry Andric selectArch(ArchFeatureName);
75760b57cec5SDimitry Andric getTargetStreamer().emitDirectiveSetArch(Arch);
75770b57cec5SDimitry Andric return false;
75780b57cec5SDimitry Andric }
75790b57cec5SDimitry Andric
parseSetFeature(uint64_t Feature)75800b57cec5SDimitry Andric bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
75810b57cec5SDimitry Andric MCAsmParser &Parser = getParser();
75820b57cec5SDimitry Andric Parser.Lex();
75830b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement))
75840b57cec5SDimitry Andric return reportParseError("unexpected token, expected end of statement");
75850b57cec5SDimitry Andric
75860b57cec5SDimitry Andric switch (Feature) {
75870b57cec5SDimitry Andric default:
75880b57cec5SDimitry Andric llvm_unreachable("Unimplemented feature");
75895ffd83dbSDimitry Andric case Mips::FeatureMips3D:
75905ffd83dbSDimitry Andric setFeatureBits(Mips::FeatureMips3D, "mips3d");
75915ffd83dbSDimitry Andric getTargetStreamer().emitDirectiveSetMips3D();
75925ffd83dbSDimitry Andric break;
75930b57cec5SDimitry Andric case Mips::FeatureDSP:
75940b57cec5SDimitry Andric setFeatureBits(Mips::FeatureDSP, "dsp");
75950b57cec5SDimitry Andric getTargetStreamer().emitDirectiveSetDsp();
75960b57cec5SDimitry Andric break;
75970b57cec5SDimitry Andric case Mips::FeatureDSPR2:
75980b57cec5SDimitry Andric setFeatureBits(Mips::FeatureDSPR2, "dspr2");
75990b57cec5SDimitry Andric getTargetStreamer().emitDirectiveSetDspr2();
76000b57cec5SDimitry Andric break;
76010b57cec5SDimitry Andric case Mips::FeatureMicroMips:
76020b57cec5SDimitry Andric setFeatureBits(Mips::FeatureMicroMips, "micromips");
76030b57cec5SDimitry Andric getTargetStreamer().emitDirectiveSetMicroMips();
76040b57cec5SDimitry Andric break;
76050b57cec5SDimitry Andric case Mips::FeatureMips1:
76060b57cec5SDimitry Andric selectArch("mips1");
76070b57cec5SDimitry Andric getTargetStreamer().emitDirectiveSetMips1();
76080b57cec5SDimitry Andric break;
76090b57cec5SDimitry Andric case Mips::FeatureMips2:
76100b57cec5SDimitry Andric selectArch("mips2");
76110b57cec5SDimitry Andric getTargetStreamer().emitDirectiveSetMips2();
76120b57cec5SDimitry Andric break;
76130b57cec5SDimitry Andric case Mips::FeatureMips3:
76140b57cec5SDimitry Andric selectArch("mips3");
76150b57cec5SDimitry Andric getTargetStreamer().emitDirectiveSetMips3();
76160b57cec5SDimitry Andric break;
76170b57cec5SDimitry Andric case Mips::FeatureMips4:
76180b57cec5SDimitry Andric selectArch("mips4");
76190b57cec5SDimitry Andric getTargetStreamer().emitDirectiveSetMips4();
76200b57cec5SDimitry Andric break;
76210b57cec5SDimitry Andric case Mips::FeatureMips5:
76220b57cec5SDimitry Andric selectArch("mips5");
76230b57cec5SDimitry Andric getTargetStreamer().emitDirectiveSetMips5();
76240b57cec5SDimitry Andric break;
76250b57cec5SDimitry Andric case Mips::FeatureMips32:
76260b57cec5SDimitry Andric selectArch("mips32");
76270b57cec5SDimitry Andric getTargetStreamer().emitDirectiveSetMips32();
76280b57cec5SDimitry Andric break;
76290b57cec5SDimitry Andric case Mips::FeatureMips32r2:
76300b57cec5SDimitry Andric selectArch("mips32r2");
76310b57cec5SDimitry Andric getTargetStreamer().emitDirectiveSetMips32R2();
76320b57cec5SDimitry Andric break;
76330b57cec5SDimitry Andric case Mips::FeatureMips32r3:
76340b57cec5SDimitry Andric selectArch("mips32r3");
76350b57cec5SDimitry Andric getTargetStreamer().emitDirectiveSetMips32R3();
76360b57cec5SDimitry Andric break;
76370b57cec5SDimitry Andric case Mips::FeatureMips32r5:
76380b57cec5SDimitry Andric selectArch("mips32r5");
76390b57cec5SDimitry Andric getTargetStreamer().emitDirectiveSetMips32R5();
76400b57cec5SDimitry Andric break;
76410b57cec5SDimitry Andric case Mips::FeatureMips32r6:
76420b57cec5SDimitry Andric selectArch("mips32r6");
76430b57cec5SDimitry Andric getTargetStreamer().emitDirectiveSetMips32R6();
76440b57cec5SDimitry Andric break;
76450b57cec5SDimitry Andric case Mips::FeatureMips64:
76460b57cec5SDimitry Andric selectArch("mips64");
76470b57cec5SDimitry Andric getTargetStreamer().emitDirectiveSetMips64();
76480b57cec5SDimitry Andric break;
76490b57cec5SDimitry Andric case Mips::FeatureMips64r2:
76500b57cec5SDimitry Andric selectArch("mips64r2");
76510b57cec5SDimitry Andric getTargetStreamer().emitDirectiveSetMips64R2();
76520b57cec5SDimitry Andric break;
76530b57cec5SDimitry Andric case Mips::FeatureMips64r3:
76540b57cec5SDimitry Andric selectArch("mips64r3");
76550b57cec5SDimitry Andric getTargetStreamer().emitDirectiveSetMips64R3();
76560b57cec5SDimitry Andric break;
76570b57cec5SDimitry Andric case Mips::FeatureMips64r5:
76580b57cec5SDimitry Andric selectArch("mips64r5");
76590b57cec5SDimitry Andric getTargetStreamer().emitDirectiveSetMips64R5();
76600b57cec5SDimitry Andric break;
76610b57cec5SDimitry Andric case Mips::FeatureMips64r6:
76620b57cec5SDimitry Andric selectArch("mips64r6");
76630b57cec5SDimitry Andric getTargetStreamer().emitDirectiveSetMips64R6();
76640b57cec5SDimitry Andric break;
76650b57cec5SDimitry Andric case Mips::FeatureCRC:
76660b57cec5SDimitry Andric setFeatureBits(Mips::FeatureCRC, "crc");
76670b57cec5SDimitry Andric getTargetStreamer().emitDirectiveSetCRC();
76680b57cec5SDimitry Andric break;
76690b57cec5SDimitry Andric case Mips::FeatureVirt:
76700b57cec5SDimitry Andric setFeatureBits(Mips::FeatureVirt, "virt");
76710b57cec5SDimitry Andric getTargetStreamer().emitDirectiveSetVirt();
76720b57cec5SDimitry Andric break;
76730b57cec5SDimitry Andric case Mips::FeatureGINV:
76740b57cec5SDimitry Andric setFeatureBits(Mips::FeatureGINV, "ginv");
76750b57cec5SDimitry Andric getTargetStreamer().emitDirectiveSetGINV();
76760b57cec5SDimitry Andric break;
76770b57cec5SDimitry Andric }
76780b57cec5SDimitry Andric return false;
76790b57cec5SDimitry Andric }
76800b57cec5SDimitry Andric
eatComma(StringRef ErrorStr)76810b57cec5SDimitry Andric bool MipsAsmParser::eatComma(StringRef ErrorStr) {
76820b57cec5SDimitry Andric MCAsmParser &Parser = getParser();
76830b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::Comma)) {
76840b57cec5SDimitry Andric SMLoc Loc = getLexer().getLoc();
76850b57cec5SDimitry Andric return Error(Loc, ErrorStr);
76860b57cec5SDimitry Andric }
76870b57cec5SDimitry Andric
76880b57cec5SDimitry Andric Parser.Lex(); // Eat the comma.
76890b57cec5SDimitry Andric return true;
76900b57cec5SDimitry Andric }
76910b57cec5SDimitry Andric
76920b57cec5SDimitry Andric // Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
76930b57cec5SDimitry Andric // In this class, it is only used for .cprestore.
76940b57cec5SDimitry Andric // FIXME: Only keep track of IsPicEnabled in one place, instead of in both
76950b57cec5SDimitry Andric // MipsTargetELFStreamer and MipsAsmParser.
isPicAndNotNxxAbi()76960b57cec5SDimitry Andric bool MipsAsmParser::isPicAndNotNxxAbi() {
76970b57cec5SDimitry Andric return inPicMode() && !(isABI_N32() || isABI_N64());
76980b57cec5SDimitry Andric }
76990b57cec5SDimitry Andric
parseDirectiveCpAdd(SMLoc Loc)77005ffd83dbSDimitry Andric bool MipsAsmParser::parseDirectiveCpAdd(SMLoc Loc) {
77015ffd83dbSDimitry Andric SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
770206c3fb27SDimitry Andric ParseStatus Res = parseAnyRegister(Reg);
770306c3fb27SDimitry Andric if (Res.isNoMatch() || Res.isFailure()) {
77045ffd83dbSDimitry Andric reportParseError("expected register");
77055ffd83dbSDimitry Andric return false;
77065ffd83dbSDimitry Andric }
77075ffd83dbSDimitry Andric
77085ffd83dbSDimitry Andric MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
77095ffd83dbSDimitry Andric if (!RegOpnd.isGPRAsmReg()) {
77105ffd83dbSDimitry Andric reportParseError(RegOpnd.getStartLoc(), "invalid register");
77115ffd83dbSDimitry Andric return false;
77125ffd83dbSDimitry Andric }
77135ffd83dbSDimitry Andric
77145ffd83dbSDimitry Andric // If this is not the end of the statement, report an error.
77155ffd83dbSDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) {
77165ffd83dbSDimitry Andric reportParseError("unexpected token, expected end of statement");
77175ffd83dbSDimitry Andric return false;
77185ffd83dbSDimitry Andric }
77195ffd83dbSDimitry Andric getParser().Lex(); // Consume the EndOfStatement.
77205ffd83dbSDimitry Andric
77215ffd83dbSDimitry Andric getTargetStreamer().emitDirectiveCpAdd(RegOpnd.getGPR32Reg());
77225ffd83dbSDimitry Andric return false;
77235ffd83dbSDimitry Andric }
77245ffd83dbSDimitry Andric
parseDirectiveCpLoad(SMLoc Loc)77250b57cec5SDimitry Andric bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
77260b57cec5SDimitry Andric if (AssemblerOptions.back()->isReorder())
77270b57cec5SDimitry Andric Warning(Loc, ".cpload should be inside a noreorder section");
77280b57cec5SDimitry Andric
77290b57cec5SDimitry Andric if (inMips16Mode()) {
77300b57cec5SDimitry Andric reportParseError(".cpload is not supported in Mips16 mode");
77310b57cec5SDimitry Andric return false;
77320b57cec5SDimitry Andric }
77330b57cec5SDimitry Andric
77340b57cec5SDimitry Andric SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
773506c3fb27SDimitry Andric ParseStatus Res = parseAnyRegister(Reg);
773606c3fb27SDimitry Andric if (Res.isNoMatch() || Res.isFailure()) {
77370b57cec5SDimitry Andric reportParseError("expected register containing function address");
77380b57cec5SDimitry Andric return false;
77390b57cec5SDimitry Andric }
77400b57cec5SDimitry Andric
77410b57cec5SDimitry Andric MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
77420b57cec5SDimitry Andric if (!RegOpnd.isGPRAsmReg()) {
77430b57cec5SDimitry Andric reportParseError(RegOpnd.getStartLoc(), "invalid register");
77440b57cec5SDimitry Andric return false;
77450b57cec5SDimitry Andric }
77460b57cec5SDimitry Andric
77470b57cec5SDimitry Andric // If this is not the end of the statement, report an error.
77480b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) {
77490b57cec5SDimitry Andric reportParseError("unexpected token, expected end of statement");
77500b57cec5SDimitry Andric return false;
77510b57cec5SDimitry Andric }
77520b57cec5SDimitry Andric
77530b57cec5SDimitry Andric getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
77540b57cec5SDimitry Andric return false;
77550b57cec5SDimitry Andric }
77560b57cec5SDimitry Andric
parseDirectiveCpLocal(SMLoc Loc)77570b57cec5SDimitry Andric bool MipsAsmParser::parseDirectiveCpLocal(SMLoc Loc) {
77580b57cec5SDimitry Andric if (!isABI_N32() && !isABI_N64()) {
77590b57cec5SDimitry Andric reportParseError(".cplocal is allowed only in N32 or N64 mode");
77600b57cec5SDimitry Andric return false;
77610b57cec5SDimitry Andric }
77620b57cec5SDimitry Andric
77630b57cec5SDimitry Andric SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
776406c3fb27SDimitry Andric ParseStatus Res = parseAnyRegister(Reg);
776506c3fb27SDimitry Andric if (Res.isNoMatch() || Res.isFailure()) {
77660b57cec5SDimitry Andric reportParseError("expected register containing global pointer");
77670b57cec5SDimitry Andric return false;
77680b57cec5SDimitry Andric }
77690b57cec5SDimitry Andric
77700b57cec5SDimitry Andric MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
77710b57cec5SDimitry Andric if (!RegOpnd.isGPRAsmReg()) {
77720b57cec5SDimitry Andric reportParseError(RegOpnd.getStartLoc(), "invalid register");
77730b57cec5SDimitry Andric return false;
77740b57cec5SDimitry Andric }
77750b57cec5SDimitry Andric
77760b57cec5SDimitry Andric // If this is not the end of the statement, report an error.
77770b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) {
77780b57cec5SDimitry Andric reportParseError("unexpected token, expected end of statement");
77790b57cec5SDimitry Andric return false;
77800b57cec5SDimitry Andric }
77810b57cec5SDimitry Andric getParser().Lex(); // Consume the EndOfStatement.
77820b57cec5SDimitry Andric
77830b57cec5SDimitry Andric unsigned NewReg = RegOpnd.getGPR32Reg();
77840b57cec5SDimitry Andric if (IsPicEnabled)
77850b57cec5SDimitry Andric GPReg = NewReg;
77860b57cec5SDimitry Andric
77870b57cec5SDimitry Andric getTargetStreamer().emitDirectiveCpLocal(NewReg);
77880b57cec5SDimitry Andric return false;
77890b57cec5SDimitry Andric }
77900b57cec5SDimitry Andric
parseDirectiveCpRestore(SMLoc Loc)77910b57cec5SDimitry Andric bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
77920b57cec5SDimitry Andric MCAsmParser &Parser = getParser();
77930b57cec5SDimitry Andric
77940b57cec5SDimitry Andric // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
77950b57cec5SDimitry Andric // is used in non-PIC mode.
77960b57cec5SDimitry Andric
77970b57cec5SDimitry Andric if (inMips16Mode()) {
77980b57cec5SDimitry Andric reportParseError(".cprestore is not supported in Mips16 mode");
77990b57cec5SDimitry Andric return false;
78000b57cec5SDimitry Andric }
78010b57cec5SDimitry Andric
78020b57cec5SDimitry Andric // Get the stack offset value.
78030b57cec5SDimitry Andric const MCExpr *StackOffset;
78040b57cec5SDimitry Andric int64_t StackOffsetVal;
78050b57cec5SDimitry Andric if (Parser.parseExpression(StackOffset)) {
78060b57cec5SDimitry Andric reportParseError("expected stack offset value");
78070b57cec5SDimitry Andric return false;
78080b57cec5SDimitry Andric }
78090b57cec5SDimitry Andric
78100b57cec5SDimitry Andric if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
78110b57cec5SDimitry Andric reportParseError("stack offset is not an absolute expression");
78120b57cec5SDimitry Andric return false;
78130b57cec5SDimitry Andric }
78140b57cec5SDimitry Andric
78150b57cec5SDimitry Andric if (StackOffsetVal < 0) {
78160b57cec5SDimitry Andric Warning(Loc, ".cprestore with negative stack offset has no effect");
78170b57cec5SDimitry Andric IsCpRestoreSet = false;
78180b57cec5SDimitry Andric } else {
78190b57cec5SDimitry Andric IsCpRestoreSet = true;
78200b57cec5SDimitry Andric CpRestoreOffset = StackOffsetVal;
78210b57cec5SDimitry Andric }
78220b57cec5SDimitry Andric
78230b57cec5SDimitry Andric // If this is not the end of the statement, report an error.
78240b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) {
78250b57cec5SDimitry Andric reportParseError("unexpected token, expected end of statement");
78260b57cec5SDimitry Andric return false;
78270b57cec5SDimitry Andric }
78280b57cec5SDimitry Andric
78290b57cec5SDimitry Andric if (!getTargetStreamer().emitDirectiveCpRestore(
78300b57cec5SDimitry Andric CpRestoreOffset, [&]() { return getATReg(Loc); }, Loc, STI))
78310b57cec5SDimitry Andric return true;
78320b57cec5SDimitry Andric Parser.Lex(); // Consume the EndOfStatement.
78330b57cec5SDimitry Andric return false;
78340b57cec5SDimitry Andric }
78350b57cec5SDimitry Andric
parseDirectiveCPSetup()78360b57cec5SDimitry Andric bool MipsAsmParser::parseDirectiveCPSetup() {
78370b57cec5SDimitry Andric MCAsmParser &Parser = getParser();
78380b57cec5SDimitry Andric unsigned FuncReg;
78390b57cec5SDimitry Andric unsigned Save;
78400b57cec5SDimitry Andric bool SaveIsReg = true;
78410b57cec5SDimitry Andric
78420b57cec5SDimitry Andric SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
784306c3fb27SDimitry Andric ParseStatus Res = parseAnyRegister(TmpReg);
784406c3fb27SDimitry Andric if (Res.isNoMatch()) {
78450b57cec5SDimitry Andric reportParseError("expected register containing function address");
78460b57cec5SDimitry Andric return false;
78470b57cec5SDimitry Andric }
78480b57cec5SDimitry Andric
78490b57cec5SDimitry Andric MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
78500b57cec5SDimitry Andric if (!FuncRegOpnd.isGPRAsmReg()) {
78510b57cec5SDimitry Andric reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
78520b57cec5SDimitry Andric return false;
78530b57cec5SDimitry Andric }
78540b57cec5SDimitry Andric
78550b57cec5SDimitry Andric FuncReg = FuncRegOpnd.getGPR32Reg();
78560b57cec5SDimitry Andric TmpReg.clear();
78570b57cec5SDimitry Andric
78580b57cec5SDimitry Andric if (!eatComma("unexpected token, expected comma"))
78590b57cec5SDimitry Andric return true;
78600b57cec5SDimitry Andric
786106c3fb27SDimitry Andric Res = parseAnyRegister(TmpReg);
786206c3fb27SDimitry Andric if (Res.isNoMatch()) {
78630b57cec5SDimitry Andric const MCExpr *OffsetExpr;
78640b57cec5SDimitry Andric int64_t OffsetVal;
78650b57cec5SDimitry Andric SMLoc ExprLoc = getLexer().getLoc();
78660b57cec5SDimitry Andric
78670b57cec5SDimitry Andric if (Parser.parseExpression(OffsetExpr) ||
78680b57cec5SDimitry Andric !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
78690b57cec5SDimitry Andric reportParseError(ExprLoc, "expected save register or stack offset");
78700b57cec5SDimitry Andric return false;
78710b57cec5SDimitry Andric }
78720b57cec5SDimitry Andric
78730b57cec5SDimitry Andric Save = OffsetVal;
78740b57cec5SDimitry Andric SaveIsReg = false;
78750b57cec5SDimitry Andric } else {
78760b57cec5SDimitry Andric MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
78770b57cec5SDimitry Andric if (!SaveOpnd.isGPRAsmReg()) {
78780b57cec5SDimitry Andric reportParseError(SaveOpnd.getStartLoc(), "invalid register");
78790b57cec5SDimitry Andric return false;
78800b57cec5SDimitry Andric }
78810b57cec5SDimitry Andric Save = SaveOpnd.getGPR32Reg();
78820b57cec5SDimitry Andric }
78830b57cec5SDimitry Andric
78840b57cec5SDimitry Andric if (!eatComma("unexpected token, expected comma"))
78850b57cec5SDimitry Andric return true;
78860b57cec5SDimitry Andric
78870b57cec5SDimitry Andric const MCExpr *Expr;
78880b57cec5SDimitry Andric if (Parser.parseExpression(Expr)) {
78890b57cec5SDimitry Andric reportParseError("expected expression");
78900b57cec5SDimitry Andric return false;
78910b57cec5SDimitry Andric }
78920b57cec5SDimitry Andric
78930b57cec5SDimitry Andric if (Expr->getKind() != MCExpr::SymbolRef) {
78940b57cec5SDimitry Andric reportParseError("expected symbol");
78950b57cec5SDimitry Andric return false;
78960b57cec5SDimitry Andric }
78970b57cec5SDimitry Andric const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
78980b57cec5SDimitry Andric
78990b57cec5SDimitry Andric CpSaveLocation = Save;
79000b57cec5SDimitry Andric CpSaveLocationIsRegister = SaveIsReg;
79010b57cec5SDimitry Andric
79020b57cec5SDimitry Andric getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
79030b57cec5SDimitry Andric SaveIsReg);
79040b57cec5SDimitry Andric return false;
79050b57cec5SDimitry Andric }
79060b57cec5SDimitry Andric
parseDirectiveCPReturn()79070b57cec5SDimitry Andric bool MipsAsmParser::parseDirectiveCPReturn() {
79080b57cec5SDimitry Andric getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
79090b57cec5SDimitry Andric CpSaveLocationIsRegister);
79100b57cec5SDimitry Andric return false;
79110b57cec5SDimitry Andric }
79120b57cec5SDimitry Andric
parseDirectiveNaN()79130b57cec5SDimitry Andric bool MipsAsmParser::parseDirectiveNaN() {
79140b57cec5SDimitry Andric MCAsmParser &Parser = getParser();
79150b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) {
79160b57cec5SDimitry Andric const AsmToken &Tok = Parser.getTok();
79170b57cec5SDimitry Andric
79180b57cec5SDimitry Andric if (Tok.getString() == "2008") {
79190b57cec5SDimitry Andric Parser.Lex();
79200b57cec5SDimitry Andric getTargetStreamer().emitDirectiveNaN2008();
79210b57cec5SDimitry Andric return false;
79220b57cec5SDimitry Andric } else if (Tok.getString() == "legacy") {
79230b57cec5SDimitry Andric Parser.Lex();
79240b57cec5SDimitry Andric getTargetStreamer().emitDirectiveNaNLegacy();
79250b57cec5SDimitry Andric return false;
79260b57cec5SDimitry Andric }
79270b57cec5SDimitry Andric }
79280b57cec5SDimitry Andric // If we don't recognize the option passed to the .nan
79290b57cec5SDimitry Andric // directive (e.g. no option or unknown option), emit an error.
79300b57cec5SDimitry Andric reportParseError("invalid option in .nan directive");
79310b57cec5SDimitry Andric return false;
79320b57cec5SDimitry Andric }
79330b57cec5SDimitry Andric
parseDirectiveSet()79340b57cec5SDimitry Andric bool MipsAsmParser::parseDirectiveSet() {
79350b57cec5SDimitry Andric const AsmToken &Tok = getParser().getTok();
79360b57cec5SDimitry Andric StringRef IdVal = Tok.getString();
79370b57cec5SDimitry Andric SMLoc Loc = Tok.getLoc();
79380b57cec5SDimitry Andric
79390b57cec5SDimitry Andric if (IdVal == "noat")
79400b57cec5SDimitry Andric return parseSetNoAtDirective();
79410b57cec5SDimitry Andric if (IdVal == "at")
79420b57cec5SDimitry Andric return parseSetAtDirective();
79430b57cec5SDimitry Andric if (IdVal == "arch")
79440b57cec5SDimitry Andric return parseSetArchDirective();
79450b57cec5SDimitry Andric if (IdVal == "bopt") {
79460b57cec5SDimitry Andric Warning(Loc, "'bopt' feature is unsupported");
79470b57cec5SDimitry Andric getParser().Lex();
79480b57cec5SDimitry Andric return false;
79490b57cec5SDimitry Andric }
79500b57cec5SDimitry Andric if (IdVal == "nobopt") {
79510b57cec5SDimitry Andric // We're already running in nobopt mode, so nothing to do.
79520b57cec5SDimitry Andric getParser().Lex();
79530b57cec5SDimitry Andric return false;
79540b57cec5SDimitry Andric }
79550b57cec5SDimitry Andric if (IdVal == "fp")
79560b57cec5SDimitry Andric return parseSetFpDirective();
79570b57cec5SDimitry Andric if (IdVal == "oddspreg")
79580b57cec5SDimitry Andric return parseSetOddSPRegDirective();
79590b57cec5SDimitry Andric if (IdVal == "nooddspreg")
79600b57cec5SDimitry Andric return parseSetNoOddSPRegDirective();
79610b57cec5SDimitry Andric if (IdVal == "pop")
79620b57cec5SDimitry Andric return parseSetPopDirective();
79630b57cec5SDimitry Andric if (IdVal == "push")
79640b57cec5SDimitry Andric return parseSetPushDirective();
79650b57cec5SDimitry Andric if (IdVal == "reorder")
79660b57cec5SDimitry Andric return parseSetReorderDirective();
79670b57cec5SDimitry Andric if (IdVal == "noreorder")
79680b57cec5SDimitry Andric return parseSetNoReorderDirective();
79690b57cec5SDimitry Andric if (IdVal == "macro")
79700b57cec5SDimitry Andric return parseSetMacroDirective();
79710b57cec5SDimitry Andric if (IdVal == "nomacro")
79720b57cec5SDimitry Andric return parseSetNoMacroDirective();
79730b57cec5SDimitry Andric if (IdVal == "mips16")
79740b57cec5SDimitry Andric return parseSetMips16Directive();
79750b57cec5SDimitry Andric if (IdVal == "nomips16")
79760b57cec5SDimitry Andric return parseSetNoMips16Directive();
79770b57cec5SDimitry Andric if (IdVal == "nomicromips") {
79780b57cec5SDimitry Andric clearFeatureBits(Mips::FeatureMicroMips, "micromips");
79790b57cec5SDimitry Andric getTargetStreamer().emitDirectiveSetNoMicroMips();
79800b57cec5SDimitry Andric getParser().eatToEndOfStatement();
79810b57cec5SDimitry Andric return false;
79820b57cec5SDimitry Andric }
79830b57cec5SDimitry Andric if (IdVal == "micromips") {
79840b57cec5SDimitry Andric if (hasMips64r6()) {
79850b57cec5SDimitry Andric Error(Loc, ".set micromips directive is not supported with MIPS64R6");
79860b57cec5SDimitry Andric return false;
79870b57cec5SDimitry Andric }
79880b57cec5SDimitry Andric return parseSetFeature(Mips::FeatureMicroMips);
79890b57cec5SDimitry Andric }
79900b57cec5SDimitry Andric if (IdVal == "mips0")
79910b57cec5SDimitry Andric return parseSetMips0Directive();
79920b57cec5SDimitry Andric if (IdVal == "mips1")
79930b57cec5SDimitry Andric return parseSetFeature(Mips::FeatureMips1);
79940b57cec5SDimitry Andric if (IdVal == "mips2")
79950b57cec5SDimitry Andric return parseSetFeature(Mips::FeatureMips2);
79960b57cec5SDimitry Andric if (IdVal == "mips3")
79970b57cec5SDimitry Andric return parseSetFeature(Mips::FeatureMips3);
79980b57cec5SDimitry Andric if (IdVal == "mips4")
79990b57cec5SDimitry Andric return parseSetFeature(Mips::FeatureMips4);
80000b57cec5SDimitry Andric if (IdVal == "mips5")
80010b57cec5SDimitry Andric return parseSetFeature(Mips::FeatureMips5);
80020b57cec5SDimitry Andric if (IdVal == "mips32")
80030b57cec5SDimitry Andric return parseSetFeature(Mips::FeatureMips32);
80040b57cec5SDimitry Andric if (IdVal == "mips32r2")
80050b57cec5SDimitry Andric return parseSetFeature(Mips::FeatureMips32r2);
80060b57cec5SDimitry Andric if (IdVal == "mips32r3")
80070b57cec5SDimitry Andric return parseSetFeature(Mips::FeatureMips32r3);
80080b57cec5SDimitry Andric if (IdVal == "mips32r5")
80090b57cec5SDimitry Andric return parseSetFeature(Mips::FeatureMips32r5);
80100b57cec5SDimitry Andric if (IdVal == "mips32r6")
80110b57cec5SDimitry Andric return parseSetFeature(Mips::FeatureMips32r6);
80120b57cec5SDimitry Andric if (IdVal == "mips64")
80130b57cec5SDimitry Andric return parseSetFeature(Mips::FeatureMips64);
80140b57cec5SDimitry Andric if (IdVal == "mips64r2")
80150b57cec5SDimitry Andric return parseSetFeature(Mips::FeatureMips64r2);
80160b57cec5SDimitry Andric if (IdVal == "mips64r3")
80170b57cec5SDimitry Andric return parseSetFeature(Mips::FeatureMips64r3);
80180b57cec5SDimitry Andric if (IdVal == "mips64r5")
80190b57cec5SDimitry Andric return parseSetFeature(Mips::FeatureMips64r5);
80200b57cec5SDimitry Andric if (IdVal == "mips64r6") {
80210b57cec5SDimitry Andric if (inMicroMipsMode()) {
80220b57cec5SDimitry Andric Error(Loc, "MIPS64R6 is not supported with microMIPS");
80230b57cec5SDimitry Andric return false;
80240b57cec5SDimitry Andric }
80250b57cec5SDimitry Andric return parseSetFeature(Mips::FeatureMips64r6);
80260b57cec5SDimitry Andric }
80270b57cec5SDimitry Andric if (IdVal == "dsp")
80280b57cec5SDimitry Andric return parseSetFeature(Mips::FeatureDSP);
80290b57cec5SDimitry Andric if (IdVal == "dspr2")
80300b57cec5SDimitry Andric return parseSetFeature(Mips::FeatureDSPR2);
80310b57cec5SDimitry Andric if (IdVal == "nodsp")
80320b57cec5SDimitry Andric return parseSetNoDspDirective();
80335ffd83dbSDimitry Andric if (IdVal == "mips3d")
80345ffd83dbSDimitry Andric return parseSetFeature(Mips::FeatureMips3D);
80355ffd83dbSDimitry Andric if (IdVal == "nomips3d")
80365ffd83dbSDimitry Andric return parseSetNoMips3DDirective();
80370b57cec5SDimitry Andric if (IdVal == "msa")
80380b57cec5SDimitry Andric return parseSetMsaDirective();
80390b57cec5SDimitry Andric if (IdVal == "nomsa")
80400b57cec5SDimitry Andric return parseSetNoMsaDirective();
80410b57cec5SDimitry Andric if (IdVal == "mt")
80420b57cec5SDimitry Andric return parseSetMtDirective();
80430b57cec5SDimitry Andric if (IdVal == "nomt")
80440b57cec5SDimitry Andric return parseSetNoMtDirective();
80450b57cec5SDimitry Andric if (IdVal == "softfloat")
80460b57cec5SDimitry Andric return parseSetSoftFloatDirective();
80470b57cec5SDimitry Andric if (IdVal == "hardfloat")
80480b57cec5SDimitry Andric return parseSetHardFloatDirective();
80490b57cec5SDimitry Andric if (IdVal == "crc")
80500b57cec5SDimitry Andric return parseSetFeature(Mips::FeatureCRC);
80510b57cec5SDimitry Andric if (IdVal == "nocrc")
80520b57cec5SDimitry Andric return parseSetNoCRCDirective();
80530b57cec5SDimitry Andric if (IdVal == "virt")
80540b57cec5SDimitry Andric return parseSetFeature(Mips::FeatureVirt);
80550b57cec5SDimitry Andric if (IdVal == "novirt")
80560b57cec5SDimitry Andric return parseSetNoVirtDirective();
80570b57cec5SDimitry Andric if (IdVal == "ginv")
80580b57cec5SDimitry Andric return parseSetFeature(Mips::FeatureGINV);
80590b57cec5SDimitry Andric if (IdVal == "noginv")
80600b57cec5SDimitry Andric return parseSetNoGINVDirective();
80610b57cec5SDimitry Andric
80620b57cec5SDimitry Andric // It is just an identifier, look for an assignment.
80630b57cec5SDimitry Andric return parseSetAssignment();
80640b57cec5SDimitry Andric }
80650b57cec5SDimitry Andric
80660b57cec5SDimitry Andric /// parseDirectiveGpWord
80670b57cec5SDimitry Andric /// ::= .gpword local_sym
parseDirectiveGpWord()80680b57cec5SDimitry Andric bool MipsAsmParser::parseDirectiveGpWord() {
80690b57cec5SDimitry Andric MCAsmParser &Parser = getParser();
80700b57cec5SDimitry Andric const MCExpr *Value;
80710b57cec5SDimitry Andric // EmitGPRel32Value requires an expression, so we are using base class
80720b57cec5SDimitry Andric // method to evaluate the expression.
80730b57cec5SDimitry Andric if (getParser().parseExpression(Value))
80740b57cec5SDimitry Andric return true;
80755ffd83dbSDimitry Andric getParser().getStreamer().emitGPRel32Value(Value);
80760b57cec5SDimitry Andric
80770b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement))
80780b57cec5SDimitry Andric return Error(getLexer().getLoc(),
80790b57cec5SDimitry Andric "unexpected token, expected end of statement");
80800b57cec5SDimitry Andric Parser.Lex(); // Eat EndOfStatement token.
80810b57cec5SDimitry Andric return false;
80820b57cec5SDimitry Andric }
80830b57cec5SDimitry Andric
80840b57cec5SDimitry Andric /// parseDirectiveGpDWord
80850b57cec5SDimitry Andric /// ::= .gpdword local_sym
parseDirectiveGpDWord()80860b57cec5SDimitry Andric bool MipsAsmParser::parseDirectiveGpDWord() {
80870b57cec5SDimitry Andric MCAsmParser &Parser = getParser();
80880b57cec5SDimitry Andric const MCExpr *Value;
80890b57cec5SDimitry Andric // EmitGPRel64Value requires an expression, so we are using base class
80900b57cec5SDimitry Andric // method to evaluate the expression.
80910b57cec5SDimitry Andric if (getParser().parseExpression(Value))
80920b57cec5SDimitry Andric return true;
80935ffd83dbSDimitry Andric getParser().getStreamer().emitGPRel64Value(Value);
80940b57cec5SDimitry Andric
80950b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement))
80960b57cec5SDimitry Andric return Error(getLexer().getLoc(),
80970b57cec5SDimitry Andric "unexpected token, expected end of statement");
80980b57cec5SDimitry Andric Parser.Lex(); // Eat EndOfStatement token.
80990b57cec5SDimitry Andric return false;
81000b57cec5SDimitry Andric }
81010b57cec5SDimitry Andric
81020b57cec5SDimitry Andric /// parseDirectiveDtpRelWord
81030b57cec5SDimitry Andric /// ::= .dtprelword tls_sym
parseDirectiveDtpRelWord()81040b57cec5SDimitry Andric bool MipsAsmParser::parseDirectiveDtpRelWord() {
81050b57cec5SDimitry Andric MCAsmParser &Parser = getParser();
81060b57cec5SDimitry Andric const MCExpr *Value;
81070b57cec5SDimitry Andric // EmitDTPRel32Value requires an expression, so we are using base class
81080b57cec5SDimitry Andric // method to evaluate the expression.
81090b57cec5SDimitry Andric if (getParser().parseExpression(Value))
81100b57cec5SDimitry Andric return true;
81115ffd83dbSDimitry Andric getParser().getStreamer().emitDTPRel32Value(Value);
81120b57cec5SDimitry Andric
81130b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement))
81140b57cec5SDimitry Andric return Error(getLexer().getLoc(),
81150b57cec5SDimitry Andric "unexpected token, expected end of statement");
81160b57cec5SDimitry Andric Parser.Lex(); // Eat EndOfStatement token.
81170b57cec5SDimitry Andric return false;
81180b57cec5SDimitry Andric }
81190b57cec5SDimitry Andric
81200b57cec5SDimitry Andric /// parseDirectiveDtpRelDWord
81210b57cec5SDimitry Andric /// ::= .dtpreldword tls_sym
parseDirectiveDtpRelDWord()81220b57cec5SDimitry Andric bool MipsAsmParser::parseDirectiveDtpRelDWord() {
81230b57cec5SDimitry Andric MCAsmParser &Parser = getParser();
81240b57cec5SDimitry Andric const MCExpr *Value;
81250b57cec5SDimitry Andric // EmitDTPRel64Value requires an expression, so we are using base class
81260b57cec5SDimitry Andric // method to evaluate the expression.
81270b57cec5SDimitry Andric if (getParser().parseExpression(Value))
81280b57cec5SDimitry Andric return true;
81295ffd83dbSDimitry Andric getParser().getStreamer().emitDTPRel64Value(Value);
81300b57cec5SDimitry Andric
81310b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement))
81320b57cec5SDimitry Andric return Error(getLexer().getLoc(),
81330b57cec5SDimitry Andric "unexpected token, expected end of statement");
81340b57cec5SDimitry Andric Parser.Lex(); // Eat EndOfStatement token.
81350b57cec5SDimitry Andric return false;
81360b57cec5SDimitry Andric }
81370b57cec5SDimitry Andric
81380b57cec5SDimitry Andric /// parseDirectiveTpRelWord
81390b57cec5SDimitry Andric /// ::= .tprelword tls_sym
parseDirectiveTpRelWord()81400b57cec5SDimitry Andric bool MipsAsmParser::parseDirectiveTpRelWord() {
81410b57cec5SDimitry Andric MCAsmParser &Parser = getParser();
81420b57cec5SDimitry Andric const MCExpr *Value;
81430b57cec5SDimitry Andric // EmitTPRel32Value requires an expression, so we are using base class
81440b57cec5SDimitry Andric // method to evaluate the expression.
81450b57cec5SDimitry Andric if (getParser().parseExpression(Value))
81460b57cec5SDimitry Andric return true;
81475ffd83dbSDimitry Andric getParser().getStreamer().emitTPRel32Value(Value);
81480b57cec5SDimitry Andric
81490b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement))
81500b57cec5SDimitry Andric return Error(getLexer().getLoc(),
81510b57cec5SDimitry Andric "unexpected token, expected end of statement");
81520b57cec5SDimitry Andric Parser.Lex(); // Eat EndOfStatement token.
81530b57cec5SDimitry Andric return false;
81540b57cec5SDimitry Andric }
81550b57cec5SDimitry Andric
81560b57cec5SDimitry Andric /// parseDirectiveTpRelDWord
81570b57cec5SDimitry Andric /// ::= .tpreldword tls_sym
parseDirectiveTpRelDWord()81580b57cec5SDimitry Andric bool MipsAsmParser::parseDirectiveTpRelDWord() {
81590b57cec5SDimitry Andric MCAsmParser &Parser = getParser();
81600b57cec5SDimitry Andric const MCExpr *Value;
81610b57cec5SDimitry Andric // EmitTPRel64Value requires an expression, so we are using base class
81620b57cec5SDimitry Andric // method to evaluate the expression.
81630b57cec5SDimitry Andric if (getParser().parseExpression(Value))
81640b57cec5SDimitry Andric return true;
81655ffd83dbSDimitry Andric getParser().getStreamer().emitTPRel64Value(Value);
81660b57cec5SDimitry Andric
81670b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement))
81680b57cec5SDimitry Andric return Error(getLexer().getLoc(),
81690b57cec5SDimitry Andric "unexpected token, expected end of statement");
81700b57cec5SDimitry Andric Parser.Lex(); // Eat EndOfStatement token.
81710b57cec5SDimitry Andric return false;
81720b57cec5SDimitry Andric }
81730b57cec5SDimitry Andric
parseDirectiveOption()81740b57cec5SDimitry Andric bool MipsAsmParser::parseDirectiveOption() {
81750b57cec5SDimitry Andric MCAsmParser &Parser = getParser();
81760b57cec5SDimitry Andric // Get the option token.
81770b57cec5SDimitry Andric AsmToken Tok = Parser.getTok();
81780b57cec5SDimitry Andric // At the moment only identifiers are supported.
81790b57cec5SDimitry Andric if (Tok.isNot(AsmToken::Identifier)) {
81800b57cec5SDimitry Andric return Error(Parser.getTok().getLoc(),
81810b57cec5SDimitry Andric "unexpected token, expected identifier");
81820b57cec5SDimitry Andric }
81830b57cec5SDimitry Andric
81840b57cec5SDimitry Andric StringRef Option = Tok.getIdentifier();
81850b57cec5SDimitry Andric
81860b57cec5SDimitry Andric if (Option == "pic0") {
81870b57cec5SDimitry Andric // MipsAsmParser needs to know if the current PIC mode changes.
81880b57cec5SDimitry Andric IsPicEnabled = false;
81890b57cec5SDimitry Andric
81900b57cec5SDimitry Andric getTargetStreamer().emitDirectiveOptionPic0();
81910b57cec5SDimitry Andric Parser.Lex();
81920b57cec5SDimitry Andric if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
81930b57cec5SDimitry Andric return Error(Parser.getTok().getLoc(),
81940b57cec5SDimitry Andric "unexpected token, expected end of statement");
81950b57cec5SDimitry Andric }
81960b57cec5SDimitry Andric return false;
81970b57cec5SDimitry Andric }
81980b57cec5SDimitry Andric
81990b57cec5SDimitry Andric if (Option == "pic2") {
82000b57cec5SDimitry Andric // MipsAsmParser needs to know if the current PIC mode changes.
82010b57cec5SDimitry Andric IsPicEnabled = true;
82020b57cec5SDimitry Andric
82030b57cec5SDimitry Andric getTargetStreamer().emitDirectiveOptionPic2();
82040b57cec5SDimitry Andric Parser.Lex();
82050b57cec5SDimitry Andric if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
82060b57cec5SDimitry Andric return Error(Parser.getTok().getLoc(),
82070b57cec5SDimitry Andric "unexpected token, expected end of statement");
82080b57cec5SDimitry Andric }
82090b57cec5SDimitry Andric return false;
82100b57cec5SDimitry Andric }
82110b57cec5SDimitry Andric
82120b57cec5SDimitry Andric // Unknown option.
82130b57cec5SDimitry Andric Warning(Parser.getTok().getLoc(),
82140b57cec5SDimitry Andric "unknown option, expected 'pic0' or 'pic2'");
82150b57cec5SDimitry Andric Parser.eatToEndOfStatement();
82160b57cec5SDimitry Andric return false;
82170b57cec5SDimitry Andric }
82180b57cec5SDimitry Andric
82190b57cec5SDimitry Andric /// parseInsnDirective
82200b57cec5SDimitry Andric /// ::= .insn
parseInsnDirective()82210b57cec5SDimitry Andric bool MipsAsmParser::parseInsnDirective() {
82220b57cec5SDimitry Andric // If this is not the end of the statement, report an error.
82230b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) {
82240b57cec5SDimitry Andric reportParseError("unexpected token, expected end of statement");
82250b57cec5SDimitry Andric return false;
82260b57cec5SDimitry Andric }
82270b57cec5SDimitry Andric
82280b57cec5SDimitry Andric // The actual label marking happens in
82290b57cec5SDimitry Andric // MipsELFStreamer::createPendingLabelRelocs().
82300b57cec5SDimitry Andric getTargetStreamer().emitDirectiveInsn();
82310b57cec5SDimitry Andric
82320b57cec5SDimitry Andric getParser().Lex(); // Eat EndOfStatement token.
82330b57cec5SDimitry Andric return false;
82340b57cec5SDimitry Andric }
82350b57cec5SDimitry Andric
82360b57cec5SDimitry Andric /// parseRSectionDirective
82370b57cec5SDimitry Andric /// ::= .rdata
parseRSectionDirective(StringRef Section)82380b57cec5SDimitry Andric bool MipsAsmParser::parseRSectionDirective(StringRef Section) {
82390b57cec5SDimitry Andric // If this is not the end of the statement, report an error.
82400b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) {
82410b57cec5SDimitry Andric reportParseError("unexpected token, expected end of statement");
82420b57cec5SDimitry Andric return false;
82430b57cec5SDimitry Andric }
82440b57cec5SDimitry Andric
82450b57cec5SDimitry Andric MCSection *ELFSection = getContext().getELFSection(
82460b57cec5SDimitry Andric Section, ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
824781ad6265SDimitry Andric getParser().getStreamer().switchSection(ELFSection);
82480b57cec5SDimitry Andric
82490b57cec5SDimitry Andric getParser().Lex(); // Eat EndOfStatement token.
82500b57cec5SDimitry Andric return false;
82510b57cec5SDimitry Andric }
82520b57cec5SDimitry Andric
82530b57cec5SDimitry Andric /// parseSSectionDirective
82540b57cec5SDimitry Andric /// ::= .sbss
82550b57cec5SDimitry Andric /// ::= .sdata
parseSSectionDirective(StringRef Section,unsigned Type)82560b57cec5SDimitry Andric bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) {
82570b57cec5SDimitry Andric // If this is not the end of the statement, report an error.
82580b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) {
82590b57cec5SDimitry Andric reportParseError("unexpected token, expected end of statement");
82600b57cec5SDimitry Andric return false;
82610b57cec5SDimitry Andric }
82620b57cec5SDimitry Andric
82630b57cec5SDimitry Andric MCSection *ELFSection = getContext().getELFSection(
82640b57cec5SDimitry Andric Section, Type, ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL);
826581ad6265SDimitry Andric getParser().getStreamer().switchSection(ELFSection);
82660b57cec5SDimitry Andric
82670b57cec5SDimitry Andric getParser().Lex(); // Eat EndOfStatement token.
82680b57cec5SDimitry Andric return false;
82690b57cec5SDimitry Andric }
82700b57cec5SDimitry Andric
82710b57cec5SDimitry Andric /// parseDirectiveModule
82720b57cec5SDimitry Andric /// ::= .module oddspreg
82730b57cec5SDimitry Andric /// ::= .module nooddspreg
82740b57cec5SDimitry Andric /// ::= .module fp=value
82750b57cec5SDimitry Andric /// ::= .module softfloat
82760b57cec5SDimitry Andric /// ::= .module hardfloat
82770b57cec5SDimitry Andric /// ::= .module mt
82780b57cec5SDimitry Andric /// ::= .module crc
82790b57cec5SDimitry Andric /// ::= .module nocrc
82800b57cec5SDimitry Andric /// ::= .module virt
82810b57cec5SDimitry Andric /// ::= .module novirt
82820b57cec5SDimitry Andric /// ::= .module ginv
82830b57cec5SDimitry Andric /// ::= .module noginv
parseDirectiveModule()82840b57cec5SDimitry Andric bool MipsAsmParser::parseDirectiveModule() {
82850b57cec5SDimitry Andric MCAsmParser &Parser = getParser();
82860b57cec5SDimitry Andric MCAsmLexer &Lexer = getLexer();
82870b57cec5SDimitry Andric SMLoc L = Lexer.getLoc();
82880b57cec5SDimitry Andric
82890b57cec5SDimitry Andric if (!getTargetStreamer().isModuleDirectiveAllowed()) {
82900b57cec5SDimitry Andric // TODO : get a better message.
82910b57cec5SDimitry Andric reportParseError(".module directive must appear before any code");
82920b57cec5SDimitry Andric return false;
82930b57cec5SDimitry Andric }
82940b57cec5SDimitry Andric
82950b57cec5SDimitry Andric StringRef Option;
82960b57cec5SDimitry Andric if (Parser.parseIdentifier(Option)) {
82970b57cec5SDimitry Andric reportParseError("expected .module option identifier");
82980b57cec5SDimitry Andric return false;
82990b57cec5SDimitry Andric }
83000b57cec5SDimitry Andric
83010b57cec5SDimitry Andric if (Option == "oddspreg") {
83020b57cec5SDimitry Andric clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
83030b57cec5SDimitry Andric
83040b57cec5SDimitry Andric // Synchronize the abiflags information with the FeatureBits information we
83050b57cec5SDimitry Andric // changed above.
83060b57cec5SDimitry Andric getTargetStreamer().updateABIInfo(*this);
83070b57cec5SDimitry Andric
83080b57cec5SDimitry Andric // If printing assembly, use the recently updated abiflags information.
83090b57cec5SDimitry Andric // If generating ELF, don't do anything (the .MIPS.abiflags section gets
83100b57cec5SDimitry Andric // emitted at the end).
83110b57cec5SDimitry Andric getTargetStreamer().emitDirectiveModuleOddSPReg();
83120b57cec5SDimitry Andric
83130b57cec5SDimitry Andric // If this is not the end of the statement, report an error.
83140b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) {
83150b57cec5SDimitry Andric reportParseError("unexpected token, expected end of statement");
83160b57cec5SDimitry Andric return false;
83170b57cec5SDimitry Andric }
83180b57cec5SDimitry Andric
83190b57cec5SDimitry Andric return false; // parseDirectiveModule has finished successfully.
83200b57cec5SDimitry Andric } else if (Option == "nooddspreg") {
83210b57cec5SDimitry Andric if (!isABI_O32()) {
83220b57cec5SDimitry Andric return Error(L, "'.module nooddspreg' requires the O32 ABI");
83230b57cec5SDimitry Andric }
83240b57cec5SDimitry Andric
83250b57cec5SDimitry Andric setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
83260b57cec5SDimitry Andric
83270b57cec5SDimitry Andric // Synchronize the abiflags information with the FeatureBits information we
83280b57cec5SDimitry Andric // changed above.
83290b57cec5SDimitry Andric getTargetStreamer().updateABIInfo(*this);
83300b57cec5SDimitry Andric
83310b57cec5SDimitry Andric // If printing assembly, use the recently updated abiflags information.
83320b57cec5SDimitry Andric // If generating ELF, don't do anything (the .MIPS.abiflags section gets
83330b57cec5SDimitry Andric // emitted at the end).
83340b57cec5SDimitry Andric getTargetStreamer().emitDirectiveModuleOddSPReg();
83350b57cec5SDimitry Andric
83360b57cec5SDimitry Andric // If this is not the end of the statement, report an error.
83370b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) {
83380b57cec5SDimitry Andric reportParseError("unexpected token, expected end of statement");
83390b57cec5SDimitry Andric return false;
83400b57cec5SDimitry Andric }
83410b57cec5SDimitry Andric
83420b57cec5SDimitry Andric return false; // parseDirectiveModule has finished successfully.
83430b57cec5SDimitry Andric } else if (Option == "fp") {
83440b57cec5SDimitry Andric return parseDirectiveModuleFP();
83450b57cec5SDimitry Andric } else if (Option == "softfloat") {
83460b57cec5SDimitry Andric setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
83470b57cec5SDimitry Andric
83480b57cec5SDimitry Andric // Synchronize the ABI Flags information with the FeatureBits information we
83490b57cec5SDimitry Andric // updated above.
83500b57cec5SDimitry Andric getTargetStreamer().updateABIInfo(*this);
83510b57cec5SDimitry Andric
83520b57cec5SDimitry Andric // If printing assembly, use the recently updated ABI Flags information.
83530b57cec5SDimitry Andric // If generating ELF, don't do anything (the .MIPS.abiflags section gets
83540b57cec5SDimitry Andric // emitted later).
83550b57cec5SDimitry Andric getTargetStreamer().emitDirectiveModuleSoftFloat();
83560b57cec5SDimitry Andric
83570b57cec5SDimitry Andric // If this is not the end of the statement, report an error.
83580b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) {
83590b57cec5SDimitry Andric reportParseError("unexpected token, expected end of statement");
83600b57cec5SDimitry Andric return false;
83610b57cec5SDimitry Andric }
83620b57cec5SDimitry Andric
83630b57cec5SDimitry Andric return false; // parseDirectiveModule has finished successfully.
83640b57cec5SDimitry Andric } else if (Option == "hardfloat") {
83650b57cec5SDimitry Andric clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
83660b57cec5SDimitry Andric
83670b57cec5SDimitry Andric // Synchronize the ABI Flags information with the FeatureBits information we
83680b57cec5SDimitry Andric // updated above.
83690b57cec5SDimitry Andric getTargetStreamer().updateABIInfo(*this);
83700b57cec5SDimitry Andric
83710b57cec5SDimitry Andric // If printing assembly, use the recently updated ABI Flags information.
83720b57cec5SDimitry Andric // If generating ELF, don't do anything (the .MIPS.abiflags section gets
83730b57cec5SDimitry Andric // emitted later).
83740b57cec5SDimitry Andric getTargetStreamer().emitDirectiveModuleHardFloat();
83750b57cec5SDimitry Andric
83760b57cec5SDimitry Andric // If this is not the end of the statement, report an error.
83770b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) {
83780b57cec5SDimitry Andric reportParseError("unexpected token, expected end of statement");
83790b57cec5SDimitry Andric return false;
83800b57cec5SDimitry Andric }
83810b57cec5SDimitry Andric
83820b57cec5SDimitry Andric return false; // parseDirectiveModule has finished successfully.
83830b57cec5SDimitry Andric } else if (Option == "mt") {
83840b57cec5SDimitry Andric setModuleFeatureBits(Mips::FeatureMT, "mt");
83850b57cec5SDimitry Andric
83860b57cec5SDimitry Andric // Synchronize the ABI Flags information with the FeatureBits information we
83870b57cec5SDimitry Andric // updated above.
83880b57cec5SDimitry Andric getTargetStreamer().updateABIInfo(*this);
83890b57cec5SDimitry Andric
83900b57cec5SDimitry Andric // If printing assembly, use the recently updated ABI Flags information.
83910b57cec5SDimitry Andric // If generating ELF, don't do anything (the .MIPS.abiflags section gets
83920b57cec5SDimitry Andric // emitted later).
83930b57cec5SDimitry Andric getTargetStreamer().emitDirectiveModuleMT();
83940b57cec5SDimitry Andric
83950b57cec5SDimitry Andric // If this is not the end of the statement, report an error.
83960b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) {
83970b57cec5SDimitry Andric reportParseError("unexpected token, expected end of statement");
83980b57cec5SDimitry Andric return false;
83990b57cec5SDimitry Andric }
84000b57cec5SDimitry Andric
84010b57cec5SDimitry Andric return false; // parseDirectiveModule has finished successfully.
84020b57cec5SDimitry Andric } else if (Option == "crc") {
84030b57cec5SDimitry Andric setModuleFeatureBits(Mips::FeatureCRC, "crc");
84040b57cec5SDimitry Andric
84050b57cec5SDimitry Andric // Synchronize the ABI Flags information with the FeatureBits information we
84060b57cec5SDimitry Andric // updated above.
84070b57cec5SDimitry Andric getTargetStreamer().updateABIInfo(*this);
84080b57cec5SDimitry Andric
84090b57cec5SDimitry Andric // If printing assembly, use the recently updated ABI Flags information.
84100b57cec5SDimitry Andric // If generating ELF, don't do anything (the .MIPS.abiflags section gets
84110b57cec5SDimitry Andric // emitted later).
84120b57cec5SDimitry Andric getTargetStreamer().emitDirectiveModuleCRC();
84130b57cec5SDimitry Andric
84140b57cec5SDimitry Andric // If this is not the end of the statement, report an error.
84150b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) {
84160b57cec5SDimitry Andric reportParseError("unexpected token, expected end of statement");
84170b57cec5SDimitry Andric return false;
84180b57cec5SDimitry Andric }
84190b57cec5SDimitry Andric
84200b57cec5SDimitry Andric return false; // parseDirectiveModule has finished successfully.
84210b57cec5SDimitry Andric } else if (Option == "nocrc") {
84220b57cec5SDimitry Andric clearModuleFeatureBits(Mips::FeatureCRC, "crc");
84230b57cec5SDimitry Andric
84240b57cec5SDimitry Andric // Synchronize the ABI Flags information with the FeatureBits information we
84250b57cec5SDimitry Andric // updated above.
84260b57cec5SDimitry Andric getTargetStreamer().updateABIInfo(*this);
84270b57cec5SDimitry Andric
84280b57cec5SDimitry Andric // If printing assembly, use the recently updated ABI Flags information.
84290b57cec5SDimitry Andric // If generating ELF, don't do anything (the .MIPS.abiflags section gets
84300b57cec5SDimitry Andric // emitted later).
84310b57cec5SDimitry Andric getTargetStreamer().emitDirectiveModuleNoCRC();
84320b57cec5SDimitry Andric
84330b57cec5SDimitry Andric // If this is not the end of the statement, report an error.
84340b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) {
84350b57cec5SDimitry Andric reportParseError("unexpected token, expected end of statement");
84360b57cec5SDimitry Andric return false;
84370b57cec5SDimitry Andric }
84380b57cec5SDimitry Andric
84390b57cec5SDimitry Andric return false; // parseDirectiveModule has finished successfully.
84400b57cec5SDimitry Andric } else if (Option == "virt") {
84410b57cec5SDimitry Andric setModuleFeatureBits(Mips::FeatureVirt, "virt");
84420b57cec5SDimitry Andric
84430b57cec5SDimitry Andric // Synchronize the ABI Flags information with the FeatureBits information we
84440b57cec5SDimitry Andric // updated above.
84450b57cec5SDimitry Andric getTargetStreamer().updateABIInfo(*this);
84460b57cec5SDimitry Andric
84470b57cec5SDimitry Andric // If printing assembly, use the recently updated ABI Flags information.
84480b57cec5SDimitry Andric // If generating ELF, don't do anything (the .MIPS.abiflags section gets
84490b57cec5SDimitry Andric // emitted later).
84500b57cec5SDimitry Andric getTargetStreamer().emitDirectiveModuleVirt();
84510b57cec5SDimitry Andric
84520b57cec5SDimitry Andric // If this is not the end of the statement, report an error.
84530b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) {
84540b57cec5SDimitry Andric reportParseError("unexpected token, expected end of statement");
84550b57cec5SDimitry Andric return false;
84560b57cec5SDimitry Andric }
84570b57cec5SDimitry Andric
84580b57cec5SDimitry Andric return false; // parseDirectiveModule has finished successfully.
84590b57cec5SDimitry Andric } else if (Option == "novirt") {
84600b57cec5SDimitry Andric clearModuleFeatureBits(Mips::FeatureVirt, "virt");
84610b57cec5SDimitry Andric
84620b57cec5SDimitry Andric // Synchronize the ABI Flags information with the FeatureBits information we
84630b57cec5SDimitry Andric // updated above.
84640b57cec5SDimitry Andric getTargetStreamer().updateABIInfo(*this);
84650b57cec5SDimitry Andric
84660b57cec5SDimitry Andric // If printing assembly, use the recently updated ABI Flags information.
84670b57cec5SDimitry Andric // If generating ELF, don't do anything (the .MIPS.abiflags section gets
84680b57cec5SDimitry Andric // emitted later).
84690b57cec5SDimitry Andric getTargetStreamer().emitDirectiveModuleNoVirt();
84700b57cec5SDimitry Andric
84710b57cec5SDimitry Andric // If this is not the end of the statement, report an error.
84720b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) {
84730b57cec5SDimitry Andric reportParseError("unexpected token, expected end of statement");
84740b57cec5SDimitry Andric return false;
84750b57cec5SDimitry Andric }
84760b57cec5SDimitry Andric
84770b57cec5SDimitry Andric return false; // parseDirectiveModule has finished successfully.
84780b57cec5SDimitry Andric } else if (Option == "ginv") {
84790b57cec5SDimitry Andric setModuleFeatureBits(Mips::FeatureGINV, "ginv");
84800b57cec5SDimitry Andric
84810b57cec5SDimitry Andric // Synchronize the ABI Flags information with the FeatureBits information we
84820b57cec5SDimitry Andric // updated above.
84830b57cec5SDimitry Andric getTargetStreamer().updateABIInfo(*this);
84840b57cec5SDimitry Andric
84850b57cec5SDimitry Andric // If printing assembly, use the recently updated ABI Flags information.
84860b57cec5SDimitry Andric // If generating ELF, don't do anything (the .MIPS.abiflags section gets
84870b57cec5SDimitry Andric // emitted later).
84880b57cec5SDimitry Andric getTargetStreamer().emitDirectiveModuleGINV();
84890b57cec5SDimitry Andric
84900b57cec5SDimitry Andric // If this is not the end of the statement, report an error.
84910b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) {
84920b57cec5SDimitry Andric reportParseError("unexpected token, expected end of statement");
84930b57cec5SDimitry Andric return false;
84940b57cec5SDimitry Andric }
84950b57cec5SDimitry Andric
84960b57cec5SDimitry Andric return false; // parseDirectiveModule has finished successfully.
84970b57cec5SDimitry Andric } else if (Option == "noginv") {
84980b57cec5SDimitry Andric clearModuleFeatureBits(Mips::FeatureGINV, "ginv");
84990b57cec5SDimitry Andric
85000b57cec5SDimitry Andric // Synchronize the ABI Flags information with the FeatureBits information we
85010b57cec5SDimitry Andric // updated above.
85020b57cec5SDimitry Andric getTargetStreamer().updateABIInfo(*this);
85030b57cec5SDimitry Andric
85040b57cec5SDimitry Andric // If printing assembly, use the recently updated ABI Flags information.
85050b57cec5SDimitry Andric // If generating ELF, don't do anything (the .MIPS.abiflags section gets
85060b57cec5SDimitry Andric // emitted later).
85070b57cec5SDimitry Andric getTargetStreamer().emitDirectiveModuleNoGINV();
85080b57cec5SDimitry Andric
85090b57cec5SDimitry Andric // If this is not the end of the statement, report an error.
85100b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) {
85110b57cec5SDimitry Andric reportParseError("unexpected token, expected end of statement");
85120b57cec5SDimitry Andric return false;
85130b57cec5SDimitry Andric }
85140b57cec5SDimitry Andric
85150b57cec5SDimitry Andric return false; // parseDirectiveModule has finished successfully.
85160b57cec5SDimitry Andric } else {
85170b57cec5SDimitry Andric return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
85180b57cec5SDimitry Andric }
85190b57cec5SDimitry Andric }
85200b57cec5SDimitry Andric
85210b57cec5SDimitry Andric /// parseDirectiveModuleFP
85220b57cec5SDimitry Andric /// ::= =32
85230b57cec5SDimitry Andric /// ::= =xx
85240b57cec5SDimitry Andric /// ::= =64
parseDirectiveModuleFP()85250b57cec5SDimitry Andric bool MipsAsmParser::parseDirectiveModuleFP() {
85260b57cec5SDimitry Andric MCAsmParser &Parser = getParser();
85270b57cec5SDimitry Andric MCAsmLexer &Lexer = getLexer();
85280b57cec5SDimitry Andric
85290b57cec5SDimitry Andric if (Lexer.isNot(AsmToken::Equal)) {
85300b57cec5SDimitry Andric reportParseError("unexpected token, expected equals sign '='");
85310b57cec5SDimitry Andric return false;
85320b57cec5SDimitry Andric }
85330b57cec5SDimitry Andric Parser.Lex(); // Eat '=' token.
85340b57cec5SDimitry Andric
85350b57cec5SDimitry Andric MipsABIFlagsSection::FpABIKind FpABI;
85360b57cec5SDimitry Andric if (!parseFpABIValue(FpABI, ".module"))
85370b57cec5SDimitry Andric return false;
85380b57cec5SDimitry Andric
85390b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) {
85400b57cec5SDimitry Andric reportParseError("unexpected token, expected end of statement");
85410b57cec5SDimitry Andric return false;
85420b57cec5SDimitry Andric }
85430b57cec5SDimitry Andric
85440b57cec5SDimitry Andric // Synchronize the abiflags information with the FeatureBits information we
85450b57cec5SDimitry Andric // changed above.
85460b57cec5SDimitry Andric getTargetStreamer().updateABIInfo(*this);
85470b57cec5SDimitry Andric
85480b57cec5SDimitry Andric // If printing assembly, use the recently updated abiflags information.
85490b57cec5SDimitry Andric // If generating ELF, don't do anything (the .MIPS.abiflags section gets
85500b57cec5SDimitry Andric // emitted at the end).
85510b57cec5SDimitry Andric getTargetStreamer().emitDirectiveModuleFP();
85520b57cec5SDimitry Andric
85530b57cec5SDimitry Andric Parser.Lex(); // Consume the EndOfStatement.
85540b57cec5SDimitry Andric return false;
85550b57cec5SDimitry Andric }
85560b57cec5SDimitry Andric
parseFpABIValue(MipsABIFlagsSection::FpABIKind & FpABI,StringRef Directive)85570b57cec5SDimitry Andric bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
85580b57cec5SDimitry Andric StringRef Directive) {
85590b57cec5SDimitry Andric MCAsmParser &Parser = getParser();
85600b57cec5SDimitry Andric MCAsmLexer &Lexer = getLexer();
85610b57cec5SDimitry Andric bool ModuleLevelOptions = Directive == ".module";
85620b57cec5SDimitry Andric
85630b57cec5SDimitry Andric if (Lexer.is(AsmToken::Identifier)) {
85640b57cec5SDimitry Andric StringRef Value = Parser.getTok().getString();
85650b57cec5SDimitry Andric Parser.Lex();
85660b57cec5SDimitry Andric
85670b57cec5SDimitry Andric if (Value != "xx") {
85680b57cec5SDimitry Andric reportParseError("unsupported value, expected 'xx', '32' or '64'");
85690b57cec5SDimitry Andric return false;
85700b57cec5SDimitry Andric }
85710b57cec5SDimitry Andric
85720b57cec5SDimitry Andric if (!isABI_O32()) {
85730b57cec5SDimitry Andric reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
85740b57cec5SDimitry Andric return false;
85750b57cec5SDimitry Andric }
85760b57cec5SDimitry Andric
85770b57cec5SDimitry Andric FpABI = MipsABIFlagsSection::FpABIKind::XX;
85780b57cec5SDimitry Andric if (ModuleLevelOptions) {
85790b57cec5SDimitry Andric setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
85800b57cec5SDimitry Andric clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
85810b57cec5SDimitry Andric } else {
85820b57cec5SDimitry Andric setFeatureBits(Mips::FeatureFPXX, "fpxx");
85830b57cec5SDimitry Andric clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
85840b57cec5SDimitry Andric }
85850b57cec5SDimitry Andric return true;
85860b57cec5SDimitry Andric }
85870b57cec5SDimitry Andric
85880b57cec5SDimitry Andric if (Lexer.is(AsmToken::Integer)) {
85890b57cec5SDimitry Andric unsigned Value = Parser.getTok().getIntVal();
85900b57cec5SDimitry Andric Parser.Lex();
85910b57cec5SDimitry Andric
85920b57cec5SDimitry Andric if (Value != 32 && Value != 64) {
85930b57cec5SDimitry Andric reportParseError("unsupported value, expected 'xx', '32' or '64'");
85940b57cec5SDimitry Andric return false;
85950b57cec5SDimitry Andric }
85960b57cec5SDimitry Andric
85970b57cec5SDimitry Andric if (Value == 32) {
85980b57cec5SDimitry Andric if (!isABI_O32()) {
85990b57cec5SDimitry Andric reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
86000b57cec5SDimitry Andric return false;
86010b57cec5SDimitry Andric }
86020b57cec5SDimitry Andric
86030b57cec5SDimitry Andric FpABI = MipsABIFlagsSection::FpABIKind::S32;
86040b57cec5SDimitry Andric if (ModuleLevelOptions) {
86050b57cec5SDimitry Andric clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
86060b57cec5SDimitry Andric clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
86070b57cec5SDimitry Andric } else {
86080b57cec5SDimitry Andric clearFeatureBits(Mips::FeatureFPXX, "fpxx");
86090b57cec5SDimitry Andric clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
86100b57cec5SDimitry Andric }
86110b57cec5SDimitry Andric } else {
86120b57cec5SDimitry Andric FpABI = MipsABIFlagsSection::FpABIKind::S64;
86130b57cec5SDimitry Andric if (ModuleLevelOptions) {
86140b57cec5SDimitry Andric clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
86150b57cec5SDimitry Andric setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
86160b57cec5SDimitry Andric } else {
86170b57cec5SDimitry Andric clearFeatureBits(Mips::FeatureFPXX, "fpxx");
86180b57cec5SDimitry Andric setFeatureBits(Mips::FeatureFP64Bit, "fp64");
86190b57cec5SDimitry Andric }
86200b57cec5SDimitry Andric }
86210b57cec5SDimitry Andric
86220b57cec5SDimitry Andric return true;
86230b57cec5SDimitry Andric }
86240b57cec5SDimitry Andric
86250b57cec5SDimitry Andric return false;
86260b57cec5SDimitry Andric }
86270b57cec5SDimitry Andric
ParseDirective(AsmToken DirectiveID)86280b57cec5SDimitry Andric bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
86290b57cec5SDimitry Andric // This returns false if this function recognizes the directive
86300b57cec5SDimitry Andric // regardless of whether it is successfully handles or reports an
86310b57cec5SDimitry Andric // error. Otherwise it returns true to give the generic parser a
86320b57cec5SDimitry Andric // chance at recognizing it.
86330b57cec5SDimitry Andric
86340b57cec5SDimitry Andric MCAsmParser &Parser = getParser();
86350b57cec5SDimitry Andric StringRef IDVal = DirectiveID.getString();
86360b57cec5SDimitry Andric
86375ffd83dbSDimitry Andric if (IDVal == ".cpadd") {
86385ffd83dbSDimitry Andric parseDirectiveCpAdd(DirectiveID.getLoc());
86395ffd83dbSDimitry Andric return false;
86405ffd83dbSDimitry Andric }
86410b57cec5SDimitry Andric if (IDVal == ".cpload") {
86420b57cec5SDimitry Andric parseDirectiveCpLoad(DirectiveID.getLoc());
86430b57cec5SDimitry Andric return false;
86440b57cec5SDimitry Andric }
86450b57cec5SDimitry Andric if (IDVal == ".cprestore") {
86460b57cec5SDimitry Andric parseDirectiveCpRestore(DirectiveID.getLoc());
86470b57cec5SDimitry Andric return false;
86480b57cec5SDimitry Andric }
86490b57cec5SDimitry Andric if (IDVal == ".cplocal") {
86500b57cec5SDimitry Andric parseDirectiveCpLocal(DirectiveID.getLoc());
86510b57cec5SDimitry Andric return false;
86520b57cec5SDimitry Andric }
86530b57cec5SDimitry Andric if (IDVal == ".ent") {
86540b57cec5SDimitry Andric StringRef SymbolName;
86550b57cec5SDimitry Andric
86560b57cec5SDimitry Andric if (Parser.parseIdentifier(SymbolName)) {
86570b57cec5SDimitry Andric reportParseError("expected identifier after .ent");
86580b57cec5SDimitry Andric return false;
86590b57cec5SDimitry Andric }
86600b57cec5SDimitry Andric
86610b57cec5SDimitry Andric // There's an undocumented extension that allows an integer to
86620b57cec5SDimitry Andric // follow the name of the procedure which AFAICS is ignored by GAS.
86630b57cec5SDimitry Andric // Example: .ent foo,2
86640b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) {
86650b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::Comma)) {
86660b57cec5SDimitry Andric // Even though we accept this undocumented extension for compatibility
86670b57cec5SDimitry Andric // reasons, the additional integer argument does not actually change
86680b57cec5SDimitry Andric // the behaviour of the '.ent' directive, so we would like to discourage
86690b57cec5SDimitry Andric // its use. We do this by not referring to the extended version in
86700b57cec5SDimitry Andric // error messages which are not directly related to its use.
86710b57cec5SDimitry Andric reportParseError("unexpected token, expected end of statement");
86720b57cec5SDimitry Andric return false;
86730b57cec5SDimitry Andric }
86740b57cec5SDimitry Andric Parser.Lex(); // Eat the comma.
86750b57cec5SDimitry Andric const MCExpr *DummyNumber;
86760b57cec5SDimitry Andric int64_t DummyNumberVal;
86770b57cec5SDimitry Andric // If the user was explicitly trying to use the extended version,
86780b57cec5SDimitry Andric // we still give helpful extension-related error messages.
86790b57cec5SDimitry Andric if (Parser.parseExpression(DummyNumber)) {
86800b57cec5SDimitry Andric reportParseError("expected number after comma");
86810b57cec5SDimitry Andric return false;
86820b57cec5SDimitry Andric }
86830b57cec5SDimitry Andric if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
86840b57cec5SDimitry Andric reportParseError("expected an absolute expression after comma");
86850b57cec5SDimitry Andric return false;
86860b57cec5SDimitry Andric }
86870b57cec5SDimitry Andric }
86880b57cec5SDimitry Andric
86890b57cec5SDimitry Andric // If this is not the end of the statement, report an error.
86900b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) {
86910b57cec5SDimitry Andric reportParseError("unexpected token, expected end of statement");
86920b57cec5SDimitry Andric return false;
86930b57cec5SDimitry Andric }
86940b57cec5SDimitry Andric
86950b57cec5SDimitry Andric MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
86960b57cec5SDimitry Andric
86970b57cec5SDimitry Andric getTargetStreamer().emitDirectiveEnt(*Sym);
86980b57cec5SDimitry Andric CurrentFn = Sym;
86990b57cec5SDimitry Andric IsCpRestoreSet = false;
87000b57cec5SDimitry Andric return false;
87010b57cec5SDimitry Andric }
87020b57cec5SDimitry Andric
87030b57cec5SDimitry Andric if (IDVal == ".end") {
87040b57cec5SDimitry Andric StringRef SymbolName;
87050b57cec5SDimitry Andric
87060b57cec5SDimitry Andric if (Parser.parseIdentifier(SymbolName)) {
87070b57cec5SDimitry Andric reportParseError("expected identifier after .end");
87080b57cec5SDimitry Andric return false;
87090b57cec5SDimitry Andric }
87100b57cec5SDimitry Andric
87110b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) {
87120b57cec5SDimitry Andric reportParseError("unexpected token, expected end of statement");
87130b57cec5SDimitry Andric return false;
87140b57cec5SDimitry Andric }
87150b57cec5SDimitry Andric
87160b57cec5SDimitry Andric if (CurrentFn == nullptr) {
87170b57cec5SDimitry Andric reportParseError(".end used without .ent");
87180b57cec5SDimitry Andric return false;
87190b57cec5SDimitry Andric }
87200b57cec5SDimitry Andric
87210b57cec5SDimitry Andric if ((SymbolName != CurrentFn->getName())) {
87220b57cec5SDimitry Andric reportParseError(".end symbol does not match .ent symbol");
87230b57cec5SDimitry Andric return false;
87240b57cec5SDimitry Andric }
87250b57cec5SDimitry Andric
87260b57cec5SDimitry Andric getTargetStreamer().emitDirectiveEnd(SymbolName);
87270b57cec5SDimitry Andric CurrentFn = nullptr;
87280b57cec5SDimitry Andric IsCpRestoreSet = false;
87290b57cec5SDimitry Andric return false;
87300b57cec5SDimitry Andric }
87310b57cec5SDimitry Andric
87320b57cec5SDimitry Andric if (IDVal == ".frame") {
87330b57cec5SDimitry Andric // .frame $stack_reg, frame_size_in_bytes, $return_reg
87340b57cec5SDimitry Andric SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
873506c3fb27SDimitry Andric ParseStatus Res = parseAnyRegister(TmpReg);
873606c3fb27SDimitry Andric if (Res.isNoMatch() || Res.isFailure()) {
87370b57cec5SDimitry Andric reportParseError("expected stack register");
87380b57cec5SDimitry Andric return false;
87390b57cec5SDimitry Andric }
87400b57cec5SDimitry Andric
87410b57cec5SDimitry Andric MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
87420b57cec5SDimitry Andric if (!StackRegOpnd.isGPRAsmReg()) {
87430b57cec5SDimitry Andric reportParseError(StackRegOpnd.getStartLoc(),
87440b57cec5SDimitry Andric "expected general purpose register");
87450b57cec5SDimitry Andric return false;
87460b57cec5SDimitry Andric }
87470b57cec5SDimitry Andric unsigned StackReg = StackRegOpnd.getGPR32Reg();
87480b57cec5SDimitry Andric
87490b57cec5SDimitry Andric if (Parser.getTok().is(AsmToken::Comma))
87500b57cec5SDimitry Andric Parser.Lex();
87510b57cec5SDimitry Andric else {
87520b57cec5SDimitry Andric reportParseError("unexpected token, expected comma");
87530b57cec5SDimitry Andric return false;
87540b57cec5SDimitry Andric }
87550b57cec5SDimitry Andric
87560b57cec5SDimitry Andric // Parse the frame size.
87570b57cec5SDimitry Andric const MCExpr *FrameSize;
87580b57cec5SDimitry Andric int64_t FrameSizeVal;
87590b57cec5SDimitry Andric
87600b57cec5SDimitry Andric if (Parser.parseExpression(FrameSize)) {
87610b57cec5SDimitry Andric reportParseError("expected frame size value");
87620b57cec5SDimitry Andric return false;
87630b57cec5SDimitry Andric }
87640b57cec5SDimitry Andric
87650b57cec5SDimitry Andric if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
87660b57cec5SDimitry Andric reportParseError("frame size not an absolute expression");
87670b57cec5SDimitry Andric return false;
87680b57cec5SDimitry Andric }
87690b57cec5SDimitry Andric
87700b57cec5SDimitry Andric if (Parser.getTok().is(AsmToken::Comma))
87710b57cec5SDimitry Andric Parser.Lex();
87720b57cec5SDimitry Andric else {
87730b57cec5SDimitry Andric reportParseError("unexpected token, expected comma");
87740b57cec5SDimitry Andric return false;
87750b57cec5SDimitry Andric }
87760b57cec5SDimitry Andric
87770b57cec5SDimitry Andric // Parse the return register.
87780b57cec5SDimitry Andric TmpReg.clear();
877906c3fb27SDimitry Andric Res = parseAnyRegister(TmpReg);
878006c3fb27SDimitry Andric if (Res.isNoMatch() || Res.isFailure()) {
87810b57cec5SDimitry Andric reportParseError("expected return register");
87820b57cec5SDimitry Andric return false;
87830b57cec5SDimitry Andric }
87840b57cec5SDimitry Andric
87850b57cec5SDimitry Andric MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
87860b57cec5SDimitry Andric if (!ReturnRegOpnd.isGPRAsmReg()) {
87870b57cec5SDimitry Andric reportParseError(ReturnRegOpnd.getStartLoc(),
87880b57cec5SDimitry Andric "expected general purpose register");
87890b57cec5SDimitry Andric return false;
87900b57cec5SDimitry Andric }
87910b57cec5SDimitry Andric
87920b57cec5SDimitry Andric // If this is not the end of the statement, report an error.
87930b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) {
87940b57cec5SDimitry Andric reportParseError("unexpected token, expected end of statement");
87950b57cec5SDimitry Andric return false;
87960b57cec5SDimitry Andric }
87970b57cec5SDimitry Andric
87980b57cec5SDimitry Andric getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
87990b57cec5SDimitry Andric ReturnRegOpnd.getGPR32Reg());
88000b57cec5SDimitry Andric IsCpRestoreSet = false;
88010b57cec5SDimitry Andric return false;
88020b57cec5SDimitry Andric }
88030b57cec5SDimitry Andric
88040b57cec5SDimitry Andric if (IDVal == ".set") {
88050b57cec5SDimitry Andric parseDirectiveSet();
88060b57cec5SDimitry Andric return false;
88070b57cec5SDimitry Andric }
88080b57cec5SDimitry Andric
88090b57cec5SDimitry Andric if (IDVal == ".mask" || IDVal == ".fmask") {
88100b57cec5SDimitry Andric // .mask bitmask, frame_offset
88110b57cec5SDimitry Andric // bitmask: One bit for each register used.
88120b57cec5SDimitry Andric // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
88130b57cec5SDimitry Andric // first register is expected to be saved.
88140b57cec5SDimitry Andric // Examples:
88150b57cec5SDimitry Andric // .mask 0x80000000, -4
88160b57cec5SDimitry Andric // .fmask 0x80000000, -4
88170b57cec5SDimitry Andric //
88180b57cec5SDimitry Andric
88190b57cec5SDimitry Andric // Parse the bitmask
88200b57cec5SDimitry Andric const MCExpr *BitMask;
88210b57cec5SDimitry Andric int64_t BitMaskVal;
88220b57cec5SDimitry Andric
88230b57cec5SDimitry Andric if (Parser.parseExpression(BitMask)) {
88240b57cec5SDimitry Andric reportParseError("expected bitmask value");
88250b57cec5SDimitry Andric return false;
88260b57cec5SDimitry Andric }
88270b57cec5SDimitry Andric
88280b57cec5SDimitry Andric if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
88290b57cec5SDimitry Andric reportParseError("bitmask not an absolute expression");
88300b57cec5SDimitry Andric return false;
88310b57cec5SDimitry Andric }
88320b57cec5SDimitry Andric
88330b57cec5SDimitry Andric if (Parser.getTok().is(AsmToken::Comma))
88340b57cec5SDimitry Andric Parser.Lex();
88350b57cec5SDimitry Andric else {
88360b57cec5SDimitry Andric reportParseError("unexpected token, expected comma");
88370b57cec5SDimitry Andric return false;
88380b57cec5SDimitry Andric }
88390b57cec5SDimitry Andric
88400b57cec5SDimitry Andric // Parse the frame_offset
88410b57cec5SDimitry Andric const MCExpr *FrameOffset;
88420b57cec5SDimitry Andric int64_t FrameOffsetVal;
88430b57cec5SDimitry Andric
88440b57cec5SDimitry Andric if (Parser.parseExpression(FrameOffset)) {
88450b57cec5SDimitry Andric reportParseError("expected frame offset value");
88460b57cec5SDimitry Andric return false;
88470b57cec5SDimitry Andric }
88480b57cec5SDimitry Andric
88490b57cec5SDimitry Andric if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
88500b57cec5SDimitry Andric reportParseError("frame offset not an absolute expression");
88510b57cec5SDimitry Andric return false;
88520b57cec5SDimitry Andric }
88530b57cec5SDimitry Andric
88540b57cec5SDimitry Andric // If this is not the end of the statement, report an error.
88550b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) {
88560b57cec5SDimitry Andric reportParseError("unexpected token, expected end of statement");
88570b57cec5SDimitry Andric return false;
88580b57cec5SDimitry Andric }
88590b57cec5SDimitry Andric
88600b57cec5SDimitry Andric if (IDVal == ".mask")
88610b57cec5SDimitry Andric getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
88620b57cec5SDimitry Andric else
88630b57cec5SDimitry Andric getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
88640b57cec5SDimitry Andric return false;
88650b57cec5SDimitry Andric }
88660b57cec5SDimitry Andric
88670b57cec5SDimitry Andric if (IDVal == ".nan")
88680b57cec5SDimitry Andric return parseDirectiveNaN();
88690b57cec5SDimitry Andric
88700b57cec5SDimitry Andric if (IDVal == ".gpword") {
88710b57cec5SDimitry Andric parseDirectiveGpWord();
88720b57cec5SDimitry Andric return false;
88730b57cec5SDimitry Andric }
88740b57cec5SDimitry Andric
88750b57cec5SDimitry Andric if (IDVal == ".gpdword") {
88760b57cec5SDimitry Andric parseDirectiveGpDWord();
88770b57cec5SDimitry Andric return false;
88780b57cec5SDimitry Andric }
88790b57cec5SDimitry Andric
88800b57cec5SDimitry Andric if (IDVal == ".dtprelword") {
88810b57cec5SDimitry Andric parseDirectiveDtpRelWord();
88820b57cec5SDimitry Andric return false;
88830b57cec5SDimitry Andric }
88840b57cec5SDimitry Andric
88850b57cec5SDimitry Andric if (IDVal == ".dtpreldword") {
88860b57cec5SDimitry Andric parseDirectiveDtpRelDWord();
88870b57cec5SDimitry Andric return false;
88880b57cec5SDimitry Andric }
88890b57cec5SDimitry Andric
88900b57cec5SDimitry Andric if (IDVal == ".tprelword") {
88910b57cec5SDimitry Andric parseDirectiveTpRelWord();
88920b57cec5SDimitry Andric return false;
88930b57cec5SDimitry Andric }
88940b57cec5SDimitry Andric
88950b57cec5SDimitry Andric if (IDVal == ".tpreldword") {
88960b57cec5SDimitry Andric parseDirectiveTpRelDWord();
88970b57cec5SDimitry Andric return false;
88980b57cec5SDimitry Andric }
88990b57cec5SDimitry Andric
89000b57cec5SDimitry Andric if (IDVal == ".option") {
89010b57cec5SDimitry Andric parseDirectiveOption();
89020b57cec5SDimitry Andric return false;
89030b57cec5SDimitry Andric }
89040b57cec5SDimitry Andric
89050b57cec5SDimitry Andric if (IDVal == ".abicalls") {
89060b57cec5SDimitry Andric getTargetStreamer().emitDirectiveAbiCalls();
89070b57cec5SDimitry Andric if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
89080b57cec5SDimitry Andric Error(Parser.getTok().getLoc(),
89090b57cec5SDimitry Andric "unexpected token, expected end of statement");
89100b57cec5SDimitry Andric }
89110b57cec5SDimitry Andric return false;
89120b57cec5SDimitry Andric }
89130b57cec5SDimitry Andric
89140b57cec5SDimitry Andric if (IDVal == ".cpsetup") {
89150b57cec5SDimitry Andric parseDirectiveCPSetup();
89160b57cec5SDimitry Andric return false;
89170b57cec5SDimitry Andric }
89180b57cec5SDimitry Andric if (IDVal == ".cpreturn") {
89190b57cec5SDimitry Andric parseDirectiveCPReturn();
89200b57cec5SDimitry Andric return false;
89210b57cec5SDimitry Andric }
89220b57cec5SDimitry Andric if (IDVal == ".module") {
89230b57cec5SDimitry Andric parseDirectiveModule();
89240b57cec5SDimitry Andric return false;
89250b57cec5SDimitry Andric }
89260b57cec5SDimitry Andric if (IDVal == ".llvm_internal_mips_reallow_module_directive") {
89270b57cec5SDimitry Andric parseInternalDirectiveReallowModule();
89280b57cec5SDimitry Andric return false;
89290b57cec5SDimitry Andric }
89300b57cec5SDimitry Andric if (IDVal == ".insn") {
89310b57cec5SDimitry Andric parseInsnDirective();
89320b57cec5SDimitry Andric return false;
89330b57cec5SDimitry Andric }
89340b57cec5SDimitry Andric if (IDVal == ".rdata") {
89350b57cec5SDimitry Andric parseRSectionDirective(".rodata");
89360b57cec5SDimitry Andric return false;
89370b57cec5SDimitry Andric }
89380b57cec5SDimitry Andric if (IDVal == ".sbss") {
89390b57cec5SDimitry Andric parseSSectionDirective(IDVal, ELF::SHT_NOBITS);
89400b57cec5SDimitry Andric return false;
89410b57cec5SDimitry Andric }
89420b57cec5SDimitry Andric if (IDVal == ".sdata") {
89430b57cec5SDimitry Andric parseSSectionDirective(IDVal, ELF::SHT_PROGBITS);
89440b57cec5SDimitry Andric return false;
89450b57cec5SDimitry Andric }
89460b57cec5SDimitry Andric
89470b57cec5SDimitry Andric return true;
89480b57cec5SDimitry Andric }
89490b57cec5SDimitry Andric
parseInternalDirectiveReallowModule()89500b57cec5SDimitry Andric bool MipsAsmParser::parseInternalDirectiveReallowModule() {
89510b57cec5SDimitry Andric // If this is not the end of the statement, report an error.
89520b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) {
89530b57cec5SDimitry Andric reportParseError("unexpected token, expected end of statement");
89540b57cec5SDimitry Andric return false;
89550b57cec5SDimitry Andric }
89560b57cec5SDimitry Andric
89570b57cec5SDimitry Andric getTargetStreamer().reallowModuleDirective();
89580b57cec5SDimitry Andric
89590b57cec5SDimitry Andric getParser().Lex(); // Eat EndOfStatement token.
89600b57cec5SDimitry Andric return false;
89610b57cec5SDimitry Andric }
89620b57cec5SDimitry Andric
LLVMInitializeMipsAsmParser()8963480093f4SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeMipsAsmParser() {
89640b57cec5SDimitry Andric RegisterMCAsmParser<MipsAsmParser> X(getTheMipsTarget());
89650b57cec5SDimitry Andric RegisterMCAsmParser<MipsAsmParser> Y(getTheMipselTarget());
89660b57cec5SDimitry Andric RegisterMCAsmParser<MipsAsmParser> A(getTheMips64Target());
89670b57cec5SDimitry Andric RegisterMCAsmParser<MipsAsmParser> B(getTheMips64elTarget());
89680b57cec5SDimitry Andric }
89690b57cec5SDimitry Andric
89700b57cec5SDimitry Andric #define GET_REGISTER_MATCHER
89710b57cec5SDimitry Andric #define GET_MATCHER_IMPLEMENTATION
89720b57cec5SDimitry Andric #define GET_MNEMONIC_SPELL_CHECKER
89730b57cec5SDimitry Andric #include "MipsGenAsmMatcher.inc"
89740b57cec5SDimitry Andric
mnemonicIsValid(StringRef Mnemonic,unsigned VariantID)89750b57cec5SDimitry Andric bool MipsAsmParser::mnemonicIsValid(StringRef Mnemonic, unsigned VariantID) {
89760b57cec5SDimitry Andric // Find the appropriate table for this asm variant.
89770b57cec5SDimitry Andric const MatchEntry *Start, *End;
89780b57cec5SDimitry Andric switch (VariantID) {
89790b57cec5SDimitry Andric default: llvm_unreachable("invalid variant!");
89800b57cec5SDimitry Andric case 0: Start = std::begin(MatchTable0); End = std::end(MatchTable0); break;
89810b57cec5SDimitry Andric }
89820b57cec5SDimitry Andric // Search the table.
89830b57cec5SDimitry Andric auto MnemonicRange = std::equal_range(Start, End, Mnemonic, LessOpcode());
89840b57cec5SDimitry Andric return MnemonicRange.first != MnemonicRange.second;
89850b57cec5SDimitry Andric }
8986