blob: 4470baf8bff33d5e8ef18eeb412bdda18ef4f931 [file] [log] [blame]
Jia Liu9f610112012-02-17 08:55:11 +00001//===-- MipsAsmParser.cpp - Parse Mips assembly to MCInst instructions ----===//
Rafael Espindola870c4e92012-01-11 03:56:41 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Eric Christophera5762812015-01-26 17:33:46 +000010#include "MCTargetDesc/MipsABIInfo.h"
Petar Jovanovica5da5882014-02-04 18:41:57 +000011#include "MCTargetDesc/MipsMCExpr.h"
Rafael Espindola870c4e92012-01-11 03:56:41 +000012#include "MCTargetDesc/MipsMCTargetDesc.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000013#include "MipsRegisterInfo.h"
Daniel Sandersa6994442015-08-18 12:33:54 +000014#include "MipsTargetObjectFile.h"
Rafael Espindolaa17151a2013-10-08 13:08:17 +000015#include "MipsTargetStreamer.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000016#include "llvm/ADT/APInt.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000017#include "llvm/ADT/SmallVector.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000018#include "llvm/ADT/StringSwitch.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000019#include "llvm/MC/MCContext.h"
20#include "llvm/MC/MCExpr.h"
21#include "llvm/MC/MCInst.h"
Daniel Sandersa771fef2014-03-24 14:05:39 +000022#include "llvm/MC/MCInstBuilder.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000023#include "llvm/MC/MCParser/MCAsmLexer.h"
24#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000025#include "llvm/MC/MCStreamer.h"
26#include "llvm/MC/MCSubtargetInfo.h"
27#include "llvm/MC/MCSymbol.h"
Akira Hatanaka7605630c2012-08-17 20:16:42 +000028#include "llvm/MC/MCTargetAsmParser.h"
Daniel Sandersb50ccf82014-04-01 10:35:28 +000029#include "llvm/Support/Debug.h"
Matheus Almeidae0d75aa2013-12-13 11:11:02 +000030#include "llvm/Support/MathExtras.h"
Daniel Sandersef638fe2014-10-03 15:37:37 +000031#include "llvm/Support/SourceMgr.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000032#include "llvm/Support/TargetRegistry.h"
Benjamin Kramer799003b2015-03-23 19:32:43 +000033#include "llvm/Support/raw_ostream.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000034#include <memory>
Rafael Espindola870c4e92012-01-11 03:56:41 +000035
36using namespace llvm;
37
Chandler Carruthe96dd892014-04-21 22:55:11 +000038#define DEBUG_TYPE "mips-asm-parser"
39
Joey Gouly0e76fa72013-09-12 10:28:05 +000040namespace llvm {
41class MCInstrInfo;
42}
43
Rafael Espindola870c4e92012-01-11 03:56:41 +000044namespace {
Jack Carter0b744b32012-10-04 02:29:46 +000045class MipsAssemblerOptions {
46public:
Toma Tabacu465acfd2015-06-09 13:33:26 +000047 MipsAssemblerOptions(const FeatureBitset &Features_) :
Toma Tabacu9db22db2014-09-09 10:15:38 +000048 ATReg(1), Reorder(true), Macro(true), Features(Features_) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000049
Toma Tabacu9db22db2014-09-09 10:15:38 +000050 MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
Toma Tabacub19cf202015-04-27 13:12:59 +000051 ATReg = Opts->getATRegIndex();
Toma Tabacu9db22db2014-09-09 10:15:38 +000052 Reorder = Opts->isReorder();
53 Macro = Opts->isMacro();
54 Features = Opts->getFeatures();
55 }
56
Toma Tabacub19cf202015-04-27 13:12:59 +000057 unsigned getATRegIndex() const { return ATReg; }
58 bool setATRegIndex(unsigned Reg) {
Toma Tabacu92dbbf12015-03-26 13:08:55 +000059 if (Reg > 31)
60 return false;
61
62 ATReg = Reg;
63 return true;
64 }
Jack Carter0b744b32012-10-04 02:29:46 +000065
Toma Tabacu9db22db2014-09-09 10:15:38 +000066 bool isReorder() const { return Reorder; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000067 void setReorder() { Reorder = true; }
68 void setNoReorder() { Reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000069
Toma Tabacu9db22db2014-09-09 10:15:38 +000070 bool isMacro() const { return Macro; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000071 void setMacro() { Macro = true; }
72 void setNoMacro() { Macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000073
Toma Tabacu465acfd2015-06-09 13:33:26 +000074 const FeatureBitset &getFeatures() const { return Features; }
75 void setFeatures(const FeatureBitset &Features_) { Features = Features_; }
Toma Tabacu9db22db2014-09-09 10:15:38 +000076
Daniel Sandersf0df2212014-08-04 12:20:00 +000077 // Set of features that are either architecture features or referenced
78 // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6).
79 // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
80 // The reason we need this mask is explained in the selectArch function.
81 // FIXME: Ideally we would like TableGen to generate this information.
Michael Kupersteindb0712f2015-05-26 10:47:10 +000082 static const FeatureBitset AllArchRelatedMask;
Daniel Sandersf0df2212014-08-04 12:20:00 +000083
Jack Carter0b744b32012-10-04 02:29:46 +000084private:
Toma Tabacu3c24b042014-09-05 15:43:21 +000085 unsigned ATReg;
86 bool Reorder;
87 bool Macro;
Toma Tabacu465acfd2015-06-09 13:33:26 +000088 FeatureBitset Features;
Jack Carter0b744b32012-10-04 02:29:46 +000089};
90}
91
Michael Kupersteindb0712f2015-05-26 10:47:10 +000092const FeatureBitset MipsAssemblerOptions::AllArchRelatedMask = {
93 Mips::FeatureMips1, Mips::FeatureMips2, Mips::FeatureMips3,
94 Mips::FeatureMips3_32, Mips::FeatureMips3_32r2, Mips::FeatureMips4,
95 Mips::FeatureMips4_32, Mips::FeatureMips4_32r2, Mips::FeatureMips5,
96 Mips::FeatureMips5_32r2, Mips::FeatureMips32, Mips::FeatureMips32r2,
97 Mips::FeatureMips32r3, Mips::FeatureMips32r5, Mips::FeatureMips32r6,
98 Mips::FeatureMips64, Mips::FeatureMips64r2, Mips::FeatureMips64r3,
99 Mips::FeatureMips64r5, Mips::FeatureMips64r6, Mips::FeatureCnMips,
100 Mips::FeatureFP64Bit, Mips::FeatureGP64Bit, Mips::FeatureNaN2008
101};
102
Jack Carter0b744b32012-10-04 02:29:46 +0000103namespace {
Rafael Espindola870c4e92012-01-11 03:56:41 +0000104class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000105 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola961d4692014-11-11 05:18:41 +0000106 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000107 return static_cast<MipsTargetStreamer &>(TS);
108 }
109
Jack Carterb4dbc172012-09-05 23:34:03 +0000110 MCSubtargetInfo &STI;
Eric Christophera5762812015-01-26 17:33:46 +0000111 MipsABIInfo ABI;
Toma Tabacu9db22db2014-09-09 10:15:38 +0000112 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
Daniel Sandersd97a6342014-08-13 10:07:34 +0000113 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
114 // nullptr, which indicates that no function is currently
115 // selected. This usually happens after an '.end func'
116 // directive.
Toma Tabacud88d79c2015-06-23 14:39:42 +0000117 bool IsLittleEndian;
Daniel Sandersa6994442015-08-18 12:33:54 +0000118 bool IsPicEnabled;
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000119 bool IsCpRestoreSet;
120 int CpRestoreOffset;
Daniel Sandersf173dda2015-09-22 10:50:09 +0000121 unsigned CpSaveLocation;
122 /// If true, then CpSaveLocation is a register, otherwise it's an offset.
123 bool CpSaveLocationIsRegister;
Jack Carter0b744b32012-10-04 02:29:46 +0000124
Daniel Sandersef638fe2014-10-03 15:37:37 +0000125 // Print a warning along with its fix-it message at the given range.
126 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
127 SMRange Range, bool ShowColors = true);
128
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000129#define GET_ASSEMBLER_HEADER
130#include "MipsGenAsmMatcher.inc"
131
Matheus Almeida595fcab2014-06-11 15:05:56 +0000132 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
133
Chad Rosier49963552012-10-13 00:26:04 +0000134 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000135 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000136 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000137 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000138
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000139 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000140 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000141
Toma Tabacu13964452014-09-04 13:23:44 +0000142 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000143
Toma Tabacu13964452014-09-04 13:23:44 +0000144 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000145
David Blaikie960ea3f2014-06-08 16:18:35 +0000146 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
147 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000148
Craig Topper56c590a2014-04-29 07:58:02 +0000149 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000150
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000151 OperandMatchResultTy parseMemOperand(OperandVector &Operands);
152 OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000153 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000154 StringRef Identifier, SMLoc S);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000155 OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands,
156 SMLoc S);
157 OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
158 OperandMatchResultTy parseImm(OperandVector &Operands);
159 OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
160 OperandMatchResultTy parseInvNum(OperandVector &Operands);
161 OperandMatchResultTy parseLSAImm(OperandVector &Operands);
162 OperandMatchResultTy parseRegisterPair(OperandVector &Operands);
163 OperandMatchResultTy parseMovePRegPair(OperandVector &Operands);
164 OperandMatchResultTy parseRegisterList(OperandVector &Operands);
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000165
David Blaikie960ea3f2014-06-08 16:18:35 +0000166 bool searchSymbolAlias(OperandVector &Operands);
167
Toma Tabacu13964452014-09-04 13:23:44 +0000168 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000169
Jack Carter30a59822012-10-04 04:03:53 +0000170 bool needsExpansion(MCInst &Inst);
171
Matheus Almeida3813d572014-06-19 14:39:14 +0000172 // Expands assembly pseudo instructions.
173 // Returns false on success, true otherwise.
174 bool expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000175 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000176
Toma Tabacu8f6603a2015-01-30 11:18:50 +0000177 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
178 SmallVectorImpl<MCInst> &Instructions);
179
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000180 bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000181 bool Is32BitImm, bool IsAddress, SMLoc IDLoc,
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000182 SmallVectorImpl<MCInst> &Instructions);
183
Toma Tabacuf712ede2015-06-17 14:31:51 +0000184 bool loadAndAddSymbolAddress(const MCExpr *SymExpr, unsigned DstReg,
185 unsigned SrcReg, bool Is32BitSym, SMLoc IDLoc,
186 SmallVectorImpl<MCInst> &Instructions);
Toma Tabacu674825c2015-06-16 12:16:24 +0000187
Toma Tabacu00e98672015-05-01 12:19:27 +0000188 bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000189 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000190
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000191 bool expandLoadAddress(unsigned DstReg, unsigned BaseReg,
192 const MCOperand &Offset, bool Is32BitAddress,
193 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000194
Jozef Kolek5cfebdd2015-01-21 12:39:30 +0000195 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
196 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000197
Jack Carter9e65aa32013-03-22 00:05:30 +0000198 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000199 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
200 bool isImmOpnd);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000201
202 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
203 SmallVectorImpl<MCInst> &Instructions);
204
Toma Tabacue1e460d2015-06-11 10:36:10 +0000205 bool expandBranchImm(MCInst &Inst, SMLoc IDLoc,
206 SmallVectorImpl<MCInst> &Instructions);
207
Toma Tabacu1a108322015-06-17 13:20:24 +0000208 bool expandCondBranches(MCInst &Inst, SMLoc IDLoc,
209 SmallVectorImpl<MCInst> &Instructions);
210
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000211 bool expandDiv(MCInst &Inst, SMLoc IDLoc,
212 SmallVectorImpl<MCInst> &Instructions, const bool IsMips64,
213 const bool Signed);
214
Toma Tabacud88d79c2015-06-23 14:39:42 +0000215 bool expandUlhu(MCInst &Inst, SMLoc IDLoc,
216 SmallVectorImpl<MCInst> &Instructions);
217
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +0000218 bool expandUlw(MCInst &Inst, SMLoc IDLoc,
219 SmallVectorImpl<MCInst> &Instructions);
220
Toma Tabacu234482a2015-03-16 12:03:39 +0000221 void createNop(bool hasShortDelaySlot, SMLoc IDLoc,
222 SmallVectorImpl<MCInst> &Instructions);
223
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000224 void createAddu(unsigned DstReg, unsigned SrcReg, unsigned TrgReg,
Toma Tabacu0b3e9782015-06-23 14:00:54 +0000225 bool Is64Bit, SmallVectorImpl<MCInst> &Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000226
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000227 void createCpRestoreMemOp(bool IsLoad, int StackOffset, SMLoc IDLoc,
228 SmallVectorImpl<MCInst> &Instructions);
229
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000230 bool reportParseError(Twine ErrorMsg);
231 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000232
Jack Carterb5cf5902013-04-17 00:18:04 +0000233 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000234 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000235
Vladimir Medic4c299852013-11-06 11:27:05 +0000236 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000237
238 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000239 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000240 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000241 bool parseSetFeature(uint64_t Feature);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000242 bool isPicAndNotNxxAbi(); // Used by .cpload, .cprestore, and .cpsetup.
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000243 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000244 bool parseDirectiveCpRestore(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000245 bool parseDirectiveCPSetup();
Daniel Sandersf173dda2015-09-22 10:50:09 +0000246 bool parseDirectiveCPReturn();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000247 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000248 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000249 bool parseDirectiveOption();
Toma Tabacu9ca50962015-04-16 09:53:47 +0000250 bool parseInsnDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000251
252 bool parseSetAtDirective();
253 bool parseSetNoAtDirective();
254 bool parseSetMacroDirective();
255 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000256 bool parseSetMsaDirective();
257 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000258 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000259 bool parseSetReorderDirective();
260 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000261 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000262 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000263 bool parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +0000264 bool parseSetOddSPRegDirective();
265 bool parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000266 bool parseSetPopDirective();
267 bool parseSetPushDirective();
Toma Tabacu29696502015-06-02 09:48:04 +0000268 bool parseSetSoftFloatDirective();
269 bool parseSetHardFloatDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000270
Jack Carterd76b2372013-03-21 21:44:16 +0000271 bool parseSetAssignment();
272
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000273 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000274 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000275 bool parseDirectiveGpDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000276 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000277 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000278 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
279 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000280
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000281 bool parseInternalDirectiveReallowModule();
282
Jack Carterdc1e35d2012-09-06 20:00:02 +0000283 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000284
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000285 bool eatComma(StringRef ErrorStr);
286
Jack Carter1ac53222013-02-20 23:11:17 +0000287 int matchCPURegisterName(StringRef Symbol);
288
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000289 int matchHWRegsRegisterName(StringRef Symbol);
290
Jack Carter873c7242013-01-12 01:03:14 +0000291 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000292
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000293 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000294
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000295 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000296
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000297 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000298
Jack Carter5dc8ac92013-09-25 23:50:44 +0000299 int matchMSA128RegisterName(StringRef Name);
300
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000301 int matchMSA128CtrlRegisterName(StringRef Name);
302
Jack Carterd0bd6422013-04-18 00:41:53 +0000303 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000304
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000305 unsigned getGPR(int RegNo);
306
Toma Tabacu89a712b2015-04-15 10:48:56 +0000307 /// Returns the internal register number for the current AT. Also checks if
308 /// the current AT is unavailable (set to $0) and gives an error if it is.
309 /// This should be used in pseudo-instruction expansions which need AT.
310 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000311
312 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000313 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000314
315 // Helper function that checks if the value of a vector index is within the
316 // boundaries of accepted values for each RegisterKind
317 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
318 bool validateMSAIndex(int Val, int RegKind);
319
Daniel Sandersf0df2212014-08-04 12:20:00 +0000320 // Selects a new architecture by updating the FeatureBits with the necessary
321 // info including implied dependencies.
322 // Internally, it clears all the feature bits related to *any* architecture
323 // and selects the new one using the ToggleFeature functionality of the
324 // MCSubtargetInfo object that handles implied dependencies. The reason we
325 // clear all the arch related bits manually is because ToggleFeature only
326 // clears the features that imply the feature being cleared and not the
327 // features implied by the feature being cleared. This is easier to see
328 // with an example:
329 // --------------------------------------------------
330 // | Feature | Implies |
331 // | -------------------------------------------------|
332 // | FeatureMips1 | None |
333 // | FeatureMips2 | FeatureMips1 |
334 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
335 // | FeatureMips4 | FeatureMips3 |
336 // | ... | |
337 // --------------------------------------------------
338 //
339 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
340 // FeatureMipsGP64 | FeatureMips1)
341 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
342 void selectArch(StringRef ArchFeature) {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000343 FeatureBitset FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000344 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
345 STI.setFeatureBits(FeatureBits);
346 setAvailableFeatures(
347 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000348 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000349 }
350
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000351 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000352 if (!(STI.getFeatureBits()[Feature])) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000353 setAvailableFeatures(
354 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000355 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000356 }
357 }
358
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000359 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000360 if (STI.getFeatureBits()[Feature]) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000361 setAvailableFeatures(
362 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000363 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000364 }
365 }
366
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000367 void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
368 setFeatureBits(Feature, FeatureString);
369 AssemblerOptions.front()->setFeatures(STI.getFeatureBits());
370 }
371
372 void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
373 clearFeatureBits(Feature, FeatureString);
374 AssemblerOptions.front()->setFeatures(STI.getFeatureBits());
375 }
376
Rafael Espindola870c4e92012-01-11 03:56:41 +0000377public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000378 enum MipsMatchResultTy {
379 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY
380#define GET_OPERAND_DIAGNOSTIC_TYPES
381#include "MipsGenAsmMatcher.inc"
382#undef GET_OPERAND_DIAGNOSTIC_TYPES
383
384 };
385
Joey Gouly0e76fa72013-09-12 10:28:05 +0000386 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000387 const MCInstrInfo &MII, const MCTargetOptions &Options)
Colin LeMahieufe2c8b82015-07-27 21:56:53 +0000388 : MCTargetAsmParser(Options), STI(sti),
Daniel Sanders50f17232015-09-15 16:17:27 +0000389 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
390 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000391 MCAsmParserExtension::Initialize(parser);
392
Toma Tabacu11e14a92015-04-21 11:50:52 +0000393 parser.addAliasForDirective(".asciiz", ".asciz");
394
Jack Carterb4dbc172012-09-05 23:34:03 +0000395 // Initialize the set of available features.
396 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000397
Toma Tabacu9db22db2014-09-09 10:15:38 +0000398 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000399 AssemblerOptions.push_back(
Toma Tabacu465acfd2015-06-09 13:33:26 +0000400 llvm::make_unique<MipsAssemblerOptions>(STI.getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000401
Toma Tabacu9db22db2014-09-09 10:15:38 +0000402 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000403 AssemblerOptions.push_back(
Toma Tabacu465acfd2015-06-09 13:33:26 +0000404 llvm::make_unique<MipsAssemblerOptions>(STI.getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000405
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000406 getTargetStreamer().updateABIInfo(*this);
407
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000408 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000409 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000410
411 CurrentFn = nullptr;
Toma Tabacud88d79c2015-06-23 14:39:42 +0000412
Daniel Sandersa6994442015-08-18 12:33:54 +0000413 IsPicEnabled =
414 (getContext().getObjectFileInfo()->getRelocM() == Reloc::PIC_);
415
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000416 IsCpRestoreSet = false;
417 CpRestoreOffset = -1;
418
Daniel Sanders50f17232015-09-15 16:17:27 +0000419 Triple TheTriple(sti.getTargetTriple());
420 if ((TheTriple.getArch() == Triple::mips) ||
421 (TheTriple.getArch() == Triple::mips64))
Toma Tabacud88d79c2015-06-23 14:39:42 +0000422 IsLittleEndian = false;
423 else
424 IsLittleEndian = true;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000425 }
426
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000427 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
428 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
429
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000430 bool isGP64bit() const { return STI.getFeatureBits()[Mips::FeatureGP64Bit]; }
431 bool isFP64bit() const { return STI.getFeatureBits()[Mips::FeatureFP64Bit]; }
Eric Christophera5762812015-01-26 17:33:46 +0000432 const MipsABIInfo &getABI() const { return ABI; }
433 bool isABI_N32() const { return ABI.IsN32(); }
434 bool isABI_N64() const { return ABI.IsN64(); }
435 bool isABI_O32() const { return ABI.IsO32(); }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000436 bool isABI_FPXX() const { return STI.getFeatureBits()[Mips::FeatureFPXX]; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000437
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000438 bool useOddSPReg() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000439 return !(STI.getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000440 }
441
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000442 bool inMicroMipsMode() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000443 return STI.getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000444 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000445 bool hasMips1() const { return STI.getFeatureBits()[Mips::FeatureMips1]; }
446 bool hasMips2() const { return STI.getFeatureBits()[Mips::FeatureMips2]; }
447 bool hasMips3() const { return STI.getFeatureBits()[Mips::FeatureMips3]; }
448 bool hasMips4() const { return STI.getFeatureBits()[Mips::FeatureMips4]; }
449 bool hasMips5() const { return STI.getFeatureBits()[Mips::FeatureMips5]; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000450 bool hasMips32() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000451 return STI.getFeatureBits()[Mips::FeatureMips32];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000452 }
453 bool hasMips64() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000454 return STI.getFeatureBits()[Mips::FeatureMips64];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000455 }
456 bool hasMips32r2() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000457 return STI.getFeatureBits()[Mips::FeatureMips32r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000458 }
459 bool hasMips64r2() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000460 return STI.getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000461 }
Daniel Sanders17793142015-02-18 16:24:50 +0000462 bool hasMips32r3() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000463 return (STI.getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000464 }
465 bool hasMips64r3() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000466 return (STI.getFeatureBits()[Mips::FeatureMips64r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000467 }
468 bool hasMips32r5() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000469 return (STI.getFeatureBits()[Mips::FeatureMips32r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000470 }
471 bool hasMips64r5() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000472 return (STI.getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000473 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000474 bool hasMips32r6() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000475 return STI.getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000476 }
477 bool hasMips64r6() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000478 return STI.getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000479 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000480
481 bool hasDSP() const { return STI.getFeatureBits()[Mips::FeatureDSP]; }
482 bool hasDSPR2() const { return STI.getFeatureBits()[Mips::FeatureDSPR2]; }
483 bool hasMSA() const { return STI.getFeatureBits()[Mips::FeatureMSA]; }
Kai Nackee0245392015-01-27 19:11:28 +0000484 bool hasCnMips() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000485 return (STI.getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000486 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000487
Daniel Sandersa6994442015-08-18 12:33:54 +0000488 bool inPicMode() {
489 return IsPicEnabled;
490 }
491
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000492 bool inMips16Mode() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000493 return STI.getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000494 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000495
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000496 bool useTraps() const {
497 return STI.getFeatureBits()[Mips::FeatureUseTCCInDIV];
498 }
499
Eric Christophere8ae3e32015-05-07 23:10:21 +0000500 bool useSoftFloat() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000501 return STI.getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000502 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000503
Toma Tabacud9d344b2015-04-27 14:05:04 +0000504 /// Warn if RegIndex is the same as the current AT.
505 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000506
507 void warnIfNoMacro(SMLoc Loc);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000508
509 bool isLittle() const { return IsLittleEndian; }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000510};
511}
512
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000513namespace {
514
515/// MipsOperand - Instances of this class represent a parsed Mips machine
516/// instruction.
517class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000518public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000519 /// Broad categories of register classes
520 /// The exact class is finalized by the render method.
521 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000522 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000523 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000524 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000525 RegKind_FCC = 4, /// FCC
526 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
527 RegKind_MSACtrl = 16, /// MSA control registers
528 RegKind_COP2 = 32, /// COP2
529 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
530 /// context).
531 RegKind_CCR = 128, /// CCR
532 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000533 RegKind_COP3 = 512, /// COP3
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000534 RegKind_COP0 = 1024, /// COP0
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000535 /// Potentially any (e.g. $1)
536 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
537 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000538 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
Jack Carter873c7242013-01-12 01:03:14 +0000539 };
540
541private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000542 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000543 k_Immediate, /// An immediate (possibly involving symbol references)
544 k_Memory, /// Base + Offset Memory Address
545 k_PhysRegister, /// A physical register from the Mips namespace
546 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000547 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000548 k_RegList, /// A physical register list
549 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000550 } Kind;
551
David Blaikie960ea3f2014-06-08 16:18:35 +0000552public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000553 MipsOperand(KindTy K, MipsAsmParser &Parser)
554 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
555
David Blaikie960ea3f2014-06-08 16:18:35 +0000556private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000557 /// For diagnostics, and checking the assembler temporary
558 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000559
Eric Christopher8996c5d2013-03-15 00:42:55 +0000560 struct Token {
561 const char *Data;
562 unsigned Length;
563 };
564
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000565 struct PhysRegOp {
566 unsigned Num; /// Register Number
567 };
568
569 struct RegIdxOp {
570 unsigned Index; /// Index into the register class
571 RegKind Kind; /// Bitfield of the kinds it could possibly be
572 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000573 };
574
575 struct ImmOp {
576 const MCExpr *Val;
577 };
578
579 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000580 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000581 const MCExpr *Off;
582 };
583
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000584 struct RegListOp {
585 SmallVector<unsigned, 10> *List;
586 };
587
Jack Carterb4dbc172012-09-05 23:34:03 +0000588 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000589 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000590 struct PhysRegOp PhysReg;
591 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000592 struct ImmOp Imm;
593 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000594 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000595 };
596
597 SMLoc StartLoc, EndLoc;
598
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000599 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000600 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
601 const MCRegisterInfo *RegInfo,
602 SMLoc S, SMLoc E,
603 MipsAsmParser &Parser) {
604 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000605 Op->RegIdx.Index = Index;
606 Op->RegIdx.RegInfo = RegInfo;
607 Op->RegIdx.Kind = RegKind;
608 Op->StartLoc = S;
609 Op->EndLoc = E;
610 return Op;
611 }
612
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000613public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000614 /// Coerce the register to GPR32 and return the real register for the current
615 /// target.
616 unsigned getGPR32Reg() const {
617 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000618 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000619 unsigned ClassID = Mips::GPR32RegClassID;
620 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000621 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000622
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000623 /// Coerce the register to GPR32 and return the real register for the current
624 /// target.
625 unsigned getGPRMM16Reg() const {
626 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
627 unsigned ClassID = Mips::GPR32RegClassID;
628 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
629 }
630
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000631 /// Coerce the register to GPR64 and return the real register for the current
632 /// target.
633 unsigned getGPR64Reg() const {
634 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
635 unsigned ClassID = Mips::GPR64RegClassID;
636 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000637 }
638
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000639private:
640 /// Coerce the register to AFGR64 and return the real register for the current
641 /// target.
642 unsigned getAFGR64Reg() const {
643 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
644 if (RegIdx.Index % 2 != 0)
645 AsmParser.Warning(StartLoc, "Float register should be even.");
646 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
647 .getRegister(RegIdx.Index / 2);
648 }
649
650 /// Coerce the register to FGR64 and return the real register for the current
651 /// target.
652 unsigned getFGR64Reg() const {
653 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
654 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
655 .getRegister(RegIdx.Index);
656 }
657
658 /// Coerce the register to FGR32 and return the real register for the current
659 /// target.
660 unsigned getFGR32Reg() const {
661 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
662 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
663 .getRegister(RegIdx.Index);
664 }
665
666 /// Coerce the register to FGRH32 and return the real register for the current
667 /// target.
668 unsigned getFGRH32Reg() const {
669 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
670 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
671 .getRegister(RegIdx.Index);
672 }
673
674 /// Coerce the register to FCC and return the real register for the current
675 /// target.
676 unsigned getFCCReg() const {
677 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
678 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
679 .getRegister(RegIdx.Index);
680 }
681
682 /// Coerce the register to MSA128 and return the real register for the current
683 /// target.
684 unsigned getMSA128Reg() const {
685 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
686 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
687 // identical
688 unsigned ClassID = Mips::MSA128BRegClassID;
689 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
690 }
691
692 /// Coerce the register to MSACtrl and return the real register for the
693 /// current target.
694 unsigned getMSACtrlReg() const {
695 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
696 unsigned ClassID = Mips::MSACtrlRegClassID;
697 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
698 }
699
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000700 /// Coerce the register to COP0 and return the real register for the
701 /// current target.
702 unsigned getCOP0Reg() const {
703 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");
704 unsigned ClassID = Mips::COP0RegClassID;
705 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
706 }
707
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000708 /// Coerce the register to COP2 and return the real register for the
709 /// current target.
710 unsigned getCOP2Reg() const {
711 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
712 unsigned ClassID = Mips::COP2RegClassID;
713 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
714 }
715
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000716 /// Coerce the register to COP3 and return the real register for the
717 /// current target.
718 unsigned getCOP3Reg() const {
719 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
720 unsigned ClassID = Mips::COP3RegClassID;
721 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
722 }
723
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000724 /// Coerce the register to ACC64DSP and return the real register for the
725 /// current target.
726 unsigned getACC64DSPReg() const {
727 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
728 unsigned ClassID = Mips::ACC64DSPRegClassID;
729 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
730 }
731
732 /// Coerce the register to HI32DSP and return the real register for the
733 /// current target.
734 unsigned getHI32DSPReg() const {
735 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
736 unsigned ClassID = Mips::HI32DSPRegClassID;
737 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
738 }
739
740 /// Coerce the register to LO32DSP and return the real register for the
741 /// current target.
742 unsigned getLO32DSPReg() const {
743 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
744 unsigned ClassID = Mips::LO32DSPRegClassID;
745 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
746 }
747
748 /// Coerce the register to CCR and return the real register for the
749 /// current target.
750 unsigned getCCRReg() const {
751 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
752 unsigned ClassID = Mips::CCRRegClassID;
753 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
754 }
755
756 /// Coerce the register to HWRegs and return the real register for the
757 /// current target.
758 unsigned getHWRegsReg() const {
759 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
760 unsigned ClassID = Mips::HWRegsRegClassID;
761 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
762 }
763
764public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000765 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000766 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000767 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000768 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000769 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000770 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000771 else
Jim Grosbache9119e42015-05-13 18:37:00 +0000772 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000773 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000774
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000775 void addRegOperands(MCInst &Inst, unsigned N) const {
776 llvm_unreachable("Use a custom parser instead");
777 }
778
Daniel Sanders21bce302014-04-01 12:35:23 +0000779 /// Render the operand to an MCInst as a GPR32
780 /// Asserts if the wrong number of operands are requested, or the operand
781 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000782 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
783 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000784 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000785 }
786
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000787 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
788 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000789 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000790 }
791
Jozef Kolek1904fa22014-11-24 14:25:53 +0000792 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
793 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000794 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +0000795 }
796
Zoran Jovanovic41688672015-02-10 16:36:20 +0000797 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
798 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000799 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000800 }
801
Daniel Sanders21bce302014-04-01 12:35:23 +0000802 /// Render the operand to an MCInst as a GPR64
803 /// Asserts if the wrong number of operands are requested, or the operand
804 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000805 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
806 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000807 Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000808 }
809
810 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
811 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000812 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000813 }
814
815 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
816 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000817 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000818 }
819
820 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
821 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000822 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000823 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000824 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000825 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
826 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000827 }
828
829 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
830 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000831 Inst.addOperand(MCOperand::createReg(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000832 }
833
834 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
835 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000836 Inst.addOperand(MCOperand::createReg(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000837 }
838
839 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
840 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000841 Inst.addOperand(MCOperand::createReg(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000842 }
843
844 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
845 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000846 Inst.addOperand(MCOperand::createReg(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000847 }
848
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000849 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
850 assert(N == 1 && "Invalid number of operands!");
851 Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
852 }
853
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000854 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
855 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000856 Inst.addOperand(MCOperand::createReg(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000857 }
858
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000859 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
860 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000861 Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000862 }
863
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000864 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
865 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000866 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000867 }
868
869 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
870 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000871 Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000872 }
873
874 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
875 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000876 Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000877 }
878
879 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
880 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000881 Inst.addOperand(MCOperand::createReg(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000882 }
883
884 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
885 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000886 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000887 }
888
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000889 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000890 assert(N == 1 && "Invalid number of operands!");
891 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000892 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000893 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000894
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000895 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000896 assert(N == 2 && "Invalid number of operands!");
897
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000898 Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
899 ? getMemBase()->getGPR64Reg()
900 : getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000901
902 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000903 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000904 }
905
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000906 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
907 assert(N == 2 && "Invalid number of operands!");
908
Jim Grosbache9119e42015-05-13 18:37:00 +0000909 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000910
911 const MCExpr *Expr = getMemOff();
912 addExpr(Inst, Expr);
913 }
914
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000915 void addRegListOperands(MCInst &Inst, unsigned N) const {
916 assert(N == 1 && "Invalid number of operands!");
917
918 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000919 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000920 }
921
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000922 void addRegPairOperands(MCInst &Inst, unsigned N) const {
923 assert(N == 2 && "Invalid number of operands!");
924 unsigned RegNo = getRegPair();
Jim Grosbache9119e42015-05-13 18:37:00 +0000925 Inst.addOperand(MCOperand::createReg(RegNo++));
926 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000927 }
928
Zoran Jovanovic41688672015-02-10 16:36:20 +0000929 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
930 assert(N == 2 && "Invalid number of operands!");
931 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000932 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000933 }
934
Craig Topper56c590a2014-04-29 07:58:02 +0000935 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000936 // As a special case until we sort out the definition of div/divu, pretend
937 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
938 if (isGPRAsmReg() && RegIdx.Index == 0)
939 return true;
940
941 return Kind == k_PhysRegister;
942 }
943 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000944 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000945 bool isConstantImm() const {
946 return isImm() && dyn_cast<MCConstantExpr>(getImm());
947 }
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +0000948 template <unsigned Bits> bool isUImm() const {
949 return isImm() && isConstantImm() && isUInt<Bits>(getConstantImm());
950 }
Craig Topper56c590a2014-04-29 07:58:02 +0000951 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000952 // Note: It's not possible to pretend that other operand kinds are tokens.
953 // The matcher emitter checks tokens first.
954 return Kind == k_Token;
955 }
Craig Topper56c590a2014-04-29 07:58:02 +0000956 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000957 bool isConstantMemOff() const {
958 return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
959 }
960 template <unsigned Bits> bool isMemWithSimmOffset() const {
Zoran Jovanovica6593ff2015-08-18 12:53:08 +0000961 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
962 && getMemBase()->isGPRAsmReg();
963 }
Zoran Jovanovic6e6a2c92015-09-16 09:14:35 +0000964 template <unsigned Bits> bool isMemWithSimmOffsetGPR() const {
965 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff()) &&
966 getMemBase()->isGPRAsmReg();
967 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000968 bool isMemWithGRPMM16Base() const {
969 return isMem() && getMemBase()->isMM16AsmReg();
970 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000971 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
972 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
973 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
974 }
Jozef Kolek12c69822014-12-23 16:16:33 +0000975 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
976 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
977 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
978 && (getMemBase()->getGPR32Reg() == Mips::SP);
979 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000980 bool isRegList16() const {
981 if (!isRegList())
982 return false;
983
984 int Size = RegList.List->size();
985 if (Size < 2 || Size > 5 || *RegList.List->begin() != Mips::S0 ||
986 RegList.List->back() != Mips::RA)
987 return false;
988
989 int PrevReg = *RegList.List->begin();
990 for (int i = 1; i < Size - 1; i++) {
991 int Reg = (*(RegList.List))[i];
992 if ( Reg != PrevReg + 1)
993 return false;
994 PrevReg = Reg;
995 }
996
997 return true;
998 }
Vladimir Medic2b953d02013-10-01 09:48:56 +0000999 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001000 bool isLSAImm() const {
1001 if (!isConstantImm())
1002 return false;
1003 int64_t Val = getConstantImm();
1004 return 1 <= Val && Val <= 4;
1005 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001006 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001007 bool isMovePRegPair() const {
1008 if (Kind != k_RegList || RegList.List->size() != 2)
1009 return false;
1010
1011 unsigned R0 = RegList.List->front();
1012 unsigned R1 = RegList.List->back();
1013
1014 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
1015 (R0 == Mips::A1 && R1 == Mips::A3) ||
1016 (R0 == Mips::A2 && R1 == Mips::A3) ||
1017 (R0 == Mips::A0 && R1 == Mips::S5) ||
1018 (R0 == Mips::A0 && R1 == Mips::S6) ||
1019 (R0 == Mips::A0 && R1 == Mips::A1) ||
1020 (R0 == Mips::A0 && R1 == Mips::A2) ||
1021 (R0 == Mips::A0 && R1 == Mips::A3))
1022 return true;
1023
1024 return false;
1025 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001026
1027 StringRef getToken() const {
1028 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001029 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001030 }
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001031 bool isRegPair() const { return Kind == k_RegPair; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001032
Craig Topper56c590a2014-04-29 07:58:02 +00001033 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001034 // As a special case until we sort out the definition of div/divu, pretend
1035 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
1036 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1037 RegIdx.Kind & RegKind_GPR)
1038 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001039
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001040 assert(Kind == k_PhysRegister && "Invalid access!");
1041 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +00001042 }
1043
Jack Carterb4dbc172012-09-05 23:34:03 +00001044 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001045 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001046 return Imm.Val;
1047 }
1048
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001049 int64_t getConstantImm() const {
1050 const MCExpr *Val = getImm();
1051 return static_cast<const MCConstantExpr *>(Val)->getValue();
1052 }
1053
1054 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001055 assert((Kind == k_Memory) && "Invalid access!");
1056 return Mem.Base;
1057 }
1058
1059 const MCExpr *getMemOff() const {
1060 assert((Kind == k_Memory) && "Invalid access!");
1061 return Mem.Off;
1062 }
1063
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001064 int64_t getConstantMemOff() const {
1065 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1066 }
1067
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001068 const SmallVectorImpl<unsigned> &getRegList() const {
1069 assert((Kind == k_RegList) && "Invalid access!");
1070 return *(RegList.List);
1071 }
1072
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001073 unsigned getRegPair() const {
1074 assert((Kind == k_RegPair) && "Invalid access!");
1075 return RegIdx.Index;
1076 }
1077
David Blaikie960ea3f2014-06-08 16:18:35 +00001078 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1079 MipsAsmParser &Parser) {
1080 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001081 Op->Tok.Data = Str.data();
1082 Op->Tok.Length = Str.size();
1083 Op->StartLoc = S;
1084 Op->EndLoc = S;
1085 return Op;
1086 }
1087
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001088 /// Create a numeric register (e.g. $1). The exact register remains
1089 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001090 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001091 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001092 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001093 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001094 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001095 }
1096
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001097 /// Create a register that is definitely a GPR.
1098 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001099 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001100 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001101 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001102 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001103 }
1104
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001105 /// Create a register that is definitely a FGR.
1106 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001107 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001108 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001109 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001110 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
1111 }
1112
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001113 /// Create a register that is definitely a HWReg.
1114 /// This is typically only used for named registers such as $hwr_cpunum.
1115 static std::unique_ptr<MipsOperand>
1116 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
1117 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1118 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
1119 }
1120
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001121 /// Create a register that is definitely an FCC.
1122 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001123 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001124 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001125 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001126 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
1127 }
1128
1129 /// Create a register that is definitely an ACC.
1130 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001131 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001132 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001133 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001134 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
1135 }
1136
1137 /// Create a register that is definitely an MSA128.
1138 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001139 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001140 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001141 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001142 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
1143 }
1144
1145 /// Create a register that is definitely an MSACtrl.
1146 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001147 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001148 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001149 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001150 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
1151 }
1152
David Blaikie960ea3f2014-06-08 16:18:35 +00001153 static std::unique_ptr<MipsOperand>
1154 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1155 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001156 Op->Imm.Val = Val;
1157 Op->StartLoc = S;
1158 Op->EndLoc = E;
1159 return Op;
1160 }
1161
David Blaikie960ea3f2014-06-08 16:18:35 +00001162 static std::unique_ptr<MipsOperand>
1163 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1164 SMLoc E, MipsAsmParser &Parser) {
1165 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1166 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001167 Op->Mem.Off = Off;
1168 Op->StartLoc = S;
1169 Op->EndLoc = E;
1170 return Op;
1171 }
1172
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001173 static std::unique_ptr<MipsOperand>
1174 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1175 MipsAsmParser &Parser) {
1176 assert (Regs.size() > 0 && "Empty list not allowed");
1177
1178 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001179 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001180 Op->StartLoc = StartLoc;
1181 Op->EndLoc = EndLoc;
1182 return Op;
1183 }
1184
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001185 static std::unique_ptr<MipsOperand>
1186 CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1187 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
1188 Op->RegIdx.Index = RegNo;
1189 Op->StartLoc = S;
1190 Op->EndLoc = E;
1191 return Op;
1192 }
1193
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001194 bool isGPRAsmReg() const {
1195 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001196 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001197 bool isMM16AsmReg() const {
1198 if (!(isRegIdx() && RegIdx.Kind))
1199 return false;
1200 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1201 || RegIdx.Index == 16 || RegIdx.Index == 17);
1202 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001203 bool isMM16AsmRegZero() const {
1204 if (!(isRegIdx() && RegIdx.Kind))
1205 return false;
1206 return (RegIdx.Index == 0 ||
1207 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1208 RegIdx.Index == 17);
1209 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001210 bool isMM16AsmRegMoveP() const {
1211 if (!(isRegIdx() && RegIdx.Kind))
1212 return false;
1213 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1214 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1215 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001216 bool isFGRAsmReg() const {
1217 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1218 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001219 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001220 bool isHWRegsAsmReg() const {
1221 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001222 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001223 bool isCCRAsmReg() const {
1224 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001225 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001226 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001227 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1228 return false;
1229 if (!AsmParser.hasEightFccRegisters())
1230 return RegIdx.Index == 0;
1231 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001232 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001233 bool isACCAsmReg() const {
1234 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001235 }
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001236 bool isCOP0AsmReg() const {
1237 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1238 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001239 bool isCOP2AsmReg() const {
1240 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001241 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001242 bool isCOP3AsmReg() const {
1243 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1244 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001245 bool isMSA128AsmReg() const {
1246 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001247 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001248 bool isMSACtrlAsmReg() const {
1249 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001250 }
1251
Jack Carterb4dbc172012-09-05 23:34:03 +00001252 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001253 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001254 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001255 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001256
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001257 virtual ~MipsOperand() {
1258 switch (Kind) {
1259 case k_Immediate:
1260 break;
1261 case k_Memory:
1262 delete Mem.Base;
1263 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001264 case k_RegList:
1265 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001266 case k_PhysRegister:
1267 case k_RegisterIndex:
1268 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001269 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001270 break;
1271 }
1272 }
1273
Craig Topper56c590a2014-04-29 07:58:02 +00001274 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001275 switch (Kind) {
1276 case k_Immediate:
1277 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001278 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001279 OS << ">";
1280 break;
1281 case k_Memory:
1282 OS << "Mem<";
1283 Mem.Base->print(OS);
1284 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001285 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001286 OS << ">";
1287 break;
1288 case k_PhysRegister:
1289 OS << "PhysReg<" << PhysReg.Num << ">";
1290 break;
1291 case k_RegisterIndex:
1292 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1293 break;
1294 case k_Token:
1295 OS << Tok.Data;
1296 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001297 case k_RegList:
1298 OS << "RegList< ";
1299 for (auto Reg : (*RegList.List))
1300 OS << Reg << " ";
1301 OS << ">";
1302 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001303 case k_RegPair:
1304 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1305 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001306 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001307 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001308}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001309} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001310
Jack Carter9e65aa32013-03-22 00:05:30 +00001311namespace llvm {
1312extern const MCInstrDesc MipsInsts[];
1313}
1314static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1315 return MipsInsts[Opcode];
1316}
1317
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001318static bool hasShortDelaySlot(unsigned Opcode) {
1319 switch (Opcode) {
1320 case Mips::JALS_MM:
1321 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001322 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001323 case Mips::BGEZALS_MM:
1324 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001325 return true;
1326 default:
1327 return false;
1328 }
1329}
1330
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001331static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1332 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1333 return &SRExpr->getSymbol();
1334 }
1335
1336 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1337 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1338 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1339
1340 if (LHSSym)
1341 return LHSSym;
1342
1343 if (RHSSym)
1344 return RHSSym;
1345
1346 return nullptr;
1347 }
1348
1349 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1350 return getSingleMCSymbol(UExpr->getSubExpr());
1351
1352 return nullptr;
1353}
1354
1355static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1356 if (isa<MCSymbolRefExpr>(Expr))
1357 return 1;
1358
1359 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1360 return countMCSymbolRefExpr(BExpr->getLHS()) +
1361 countMCSymbolRefExpr(BExpr->getRHS());
1362
1363 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1364 return countMCSymbolRefExpr(UExpr->getSubExpr());
1365
1366 return 0;
1367}
1368
Jack Carter9e65aa32013-03-22 00:05:30 +00001369bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001370 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001371 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001372 bool ExpandedJalSym = false;
Daniel Sandersa771fef2014-03-24 14:05:39 +00001373
Jack Carter9e65aa32013-03-22 00:05:30 +00001374 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001375
1376 if (MCID.isBranch() || MCID.isCall()) {
1377 const unsigned Opcode = Inst.getOpcode();
1378 MCOperand Offset;
1379
1380 switch (Opcode) {
1381 default:
1382 break;
Kai Nackee0245392015-01-27 19:11:28 +00001383 case Mips::BBIT0:
1384 case Mips::BBIT032:
1385 case Mips::BBIT1:
1386 case Mips::BBIT132:
1387 assert(hasCnMips() && "instruction only valid for octeon cpus");
1388 // Fall through
1389
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001390 case Mips::BEQ:
1391 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001392 case Mips::BEQ_MM:
1393 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001394 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001395 Offset = Inst.getOperand(2);
1396 if (!Offset.isImm())
1397 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001398 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001399 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001400 if (OffsetToAlignment(Offset.getImm(),
1401 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001402 return Error(IDLoc, "branch to misaligned address");
1403 break;
1404 case Mips::BGEZ:
1405 case Mips::BGTZ:
1406 case Mips::BLEZ:
1407 case Mips::BLTZ:
1408 case Mips::BGEZAL:
1409 case Mips::BLTZAL:
1410 case Mips::BC1F:
1411 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001412 case Mips::BGEZ_MM:
1413 case Mips::BGTZ_MM:
1414 case Mips::BLEZ_MM:
1415 case Mips::BLTZ_MM:
1416 case Mips::BGEZAL_MM:
1417 case Mips::BLTZAL_MM:
1418 case Mips::BC1F_MM:
1419 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001420 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001421 Offset = Inst.getOperand(1);
1422 if (!Offset.isImm())
1423 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001424 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001425 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001426 if (OffsetToAlignment(Offset.getImm(),
1427 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001428 return Error(IDLoc, "branch to misaligned address");
1429 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001430 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001431 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001432 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001433 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001434 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1435 Offset = Inst.getOperand(1);
1436 if (!Offset.isImm())
1437 break; // We'll deal with this situation later on when applying fixups.
1438 if (!isIntN(8, Offset.getImm()))
1439 return Error(IDLoc, "branch target out of range");
1440 if (OffsetToAlignment(Offset.getImm(), 2LL))
1441 return Error(IDLoc, "branch to misaligned address");
1442 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001443 }
1444 }
1445
Daniel Sandersa84989a2014-06-16 13:25:35 +00001446 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1447 // We still accept it but it is a normal nop.
1448 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1449 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1450 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1451 "nop instruction");
1452 }
1453
Kai Nackee0245392015-01-27 19:11:28 +00001454 if (hasCnMips()) {
1455 const unsigned Opcode = Inst.getOpcode();
1456 MCOperand Opnd;
1457 int Imm;
1458
1459 switch (Opcode) {
1460 default:
1461 break;
1462
1463 case Mips::BBIT0:
1464 case Mips::BBIT032:
1465 case Mips::BBIT1:
1466 case Mips::BBIT132:
1467 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1468 // The offset is handled above
1469 Opnd = Inst.getOperand(1);
1470 if (!Opnd.isImm())
1471 return Error(IDLoc, "expected immediate operand kind");
1472 Imm = Opnd.getImm();
1473 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1474 Opcode == Mips::BBIT1 ? 63 : 31))
1475 return Error(IDLoc, "immediate operand value out of range");
1476 if (Imm > 31) {
1477 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1478 : Mips::BBIT132);
1479 Inst.getOperand(1).setImm(Imm - 32);
1480 }
1481 break;
1482
1483 case Mips::CINS:
1484 case Mips::CINS32:
1485 case Mips::EXTS:
1486 case Mips::EXTS32:
1487 assert(MCID.getNumOperands() == 4 && "unexpected number of operands");
1488 // Check length
1489 Opnd = Inst.getOperand(3);
1490 if (!Opnd.isImm())
1491 return Error(IDLoc, "expected immediate operand kind");
1492 Imm = Opnd.getImm();
1493 if (Imm < 0 || Imm > 31)
1494 return Error(IDLoc, "immediate operand value out of range");
1495 // Check position
1496 Opnd = Inst.getOperand(2);
1497 if (!Opnd.isImm())
1498 return Error(IDLoc, "expected immediate operand kind");
1499 Imm = Opnd.getImm();
1500 if (Imm < 0 || Imm > (Opcode == Mips::CINS ||
1501 Opcode == Mips::EXTS ? 63 : 31))
1502 return Error(IDLoc, "immediate operand value out of range");
1503 if (Imm > 31) {
1504 Inst.setOpcode(Opcode == Mips::CINS ? Mips::CINS32 : Mips::EXTS32);
1505 Inst.getOperand(2).setImm(Imm - 32);
1506 }
1507 break;
1508
1509 case Mips::SEQi:
1510 case Mips::SNEi:
1511 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1512 Opnd = Inst.getOperand(2);
1513 if (!Opnd.isImm())
1514 return Error(IDLoc, "expected immediate operand kind");
1515 Imm = Opnd.getImm();
1516 if (!isInt<10>(Imm))
1517 return Error(IDLoc, "immediate operand value out of range");
1518 break;
1519 }
1520 }
1521
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001522 // This expansion is not in a function called by expandInstruction() because
1523 // the pseudo-instruction doesn't have a distinct opcode.
1524 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
1525 inPicMode()) {
1526 warnIfNoMacro(IDLoc);
1527
1528 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
1529
1530 // We can do this expansion if there's only 1 symbol in the argument
1531 // expression.
1532 if (countMCSymbolRefExpr(JalExpr) > 1)
1533 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
1534
1535 // FIXME: This is checking the expression can be handled by the later stages
1536 // of the assembler. We ought to leave it to those later stages but
1537 // we can't do that until we stop evaluateRelocExpr() rewriting the
1538 // expressions into non-equivalent forms.
1539 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
1540
1541 // FIXME: Add support for label+offset operands (currently causes an error).
1542 // FIXME: Add support for forward-declared local symbols.
1543 // FIXME: Add expansion for when the LargeGOT option is enabled.
1544 if (JalSym->isInSection() || JalSym->isTemporary()) {
1545 if (isABI_O32()) {
1546 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001547 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001548 // R_(MICRO)MIPS_GOT16 label
1549 // addiu $25, $25, 0
1550 // R_(MICRO)MIPS_LO16 label
1551 // jalr $25
1552 const MCExpr *Got16RelocExpr = evaluateRelocExpr(JalExpr, "got");
1553 const MCExpr *Lo16RelocExpr = evaluateRelocExpr(JalExpr, "lo");
1554
1555 MCInst LwInst;
1556 LwInst.setOpcode(Mips::LW);
1557 LwInst.addOperand(MCOperand::createReg(Mips::T9));
1558 LwInst.addOperand(MCOperand::createReg(Mips::GP));
1559 LwInst.addOperand(MCOperand::createExpr(Got16RelocExpr));
1560 Instructions.push_back(LwInst);
1561
1562 MCInst AddiuInst;
1563 AddiuInst.setOpcode(Mips::ADDiu);
1564 AddiuInst.addOperand(MCOperand::createReg(Mips::T9));
1565 AddiuInst.addOperand(MCOperand::createReg(Mips::T9));
1566 AddiuInst.addOperand(MCOperand::createExpr(Lo16RelocExpr));
1567 Instructions.push_back(AddiuInst);
1568 } else if (isABI_N32() || isABI_N64()) {
1569 // If it's a local symbol and the N32/N64 ABIs are being used,
1570 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001571 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001572 // R_(MICRO)MIPS_GOT_DISP label
1573 // jalr $25
1574 const MCExpr *GotDispRelocExpr = evaluateRelocExpr(JalExpr, "got_disp");
1575
1576 MCInst LoadInst;
1577 LoadInst.setOpcode(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW);
1578 LoadInst.addOperand(MCOperand::createReg(Mips::T9));
1579 LoadInst.addOperand(MCOperand::createReg(Mips::GP));
1580 LoadInst.addOperand(MCOperand::createExpr(GotDispRelocExpr));
1581 Instructions.push_back(LoadInst);
1582 }
1583 } else {
1584 // If it's an external/weak symbol, we expand to:
1585 // lw/ld $25, 0($gp)
1586 // R_(MICRO)MIPS_CALL16 label
1587 // jalr $25
1588 const MCExpr *Call16RelocExpr = evaluateRelocExpr(JalExpr, "call16");
1589
1590 MCInst LoadInst;
1591 LoadInst.setOpcode(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW);
1592 LoadInst.addOperand(MCOperand::createReg(Mips::T9));
1593 LoadInst.addOperand(MCOperand::createReg(Mips::GP));
1594 LoadInst.addOperand(MCOperand::createExpr(Call16RelocExpr));
1595 Instructions.push_back(LoadInst);
1596 }
1597
1598 MCInst JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001599 if (IsCpRestoreSet && inMicroMipsMode())
1600 JalrInst.setOpcode(Mips::JALRS_MM);
1601 else
1602 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001603 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
1604 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
1605
1606 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
1607 // This relocation is supposed to be an optimization hint for the linker
1608 // and is not necessary for correctness.
1609
1610 Inst = JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001611 ExpandedJalSym = true;
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001612 }
1613
Jack Carter9e65aa32013-03-22 00:05:30 +00001614 if (MCID.mayLoad() || MCID.mayStore()) {
1615 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001616 // reference or immediate we may have to expand instructions.
1617 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001618 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001619 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1620 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001621 MCOperand &Op = Inst.getOperand(i);
1622 if (Op.isImm()) {
1623 int MemOffset = Op.getImm();
1624 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001625 // Offset can't exceed 16bit value.
1626 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001627 return false;
1628 }
1629 } else if (Op.isExpr()) {
1630 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001631 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001632 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001633 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001634 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001635 // Expand symbol.
1636 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001637 return false;
1638 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001639 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001640 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001641 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001642 }
1643 }
1644 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001645 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001646 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001647
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001648 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001649 if (MCID.mayLoad()) {
1650 // Try to create 16-bit GP relative load instruction.
1651 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1652 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1653 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1654 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1655 MCOperand &Op = Inst.getOperand(i);
1656 if (Op.isImm()) {
1657 int MemOffset = Op.getImm();
1658 MCOperand &DstReg = Inst.getOperand(0);
1659 MCOperand &BaseReg = Inst.getOperand(1);
1660 if (isIntN(9, MemOffset) && (MemOffset % 4 == 0) &&
1661 getContext().getRegisterInfo()->getRegClass(
1662 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00001663 (BaseReg.getReg() == Mips::GP ||
1664 BaseReg.getReg() == Mips::GP_64)) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001665 MCInst TmpInst;
1666 TmpInst.setLoc(IDLoc);
1667 TmpInst.setOpcode(Mips::LWGP_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00001668 TmpInst.addOperand(MCOperand::createReg(DstReg.getReg()));
1669 TmpInst.addOperand(MCOperand::createReg(Mips::GP));
1670 TmpInst.addOperand(MCOperand::createImm(MemOffset));
Jozef Koleke10a02e2015-01-28 17:27:26 +00001671 Instructions.push_back(TmpInst);
1672 return false;
1673 }
1674 }
1675 }
1676 } // for
1677 } // if load
1678
1679 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1680
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001681 MCOperand Opnd;
1682 int Imm;
1683
1684 switch (Inst.getOpcode()) {
1685 default:
1686 break;
1687 case Mips::ADDIUS5_MM:
1688 Opnd = Inst.getOperand(2);
1689 if (!Opnd.isImm())
1690 return Error(IDLoc, "expected immediate operand kind");
1691 Imm = Opnd.getImm();
1692 if (Imm < -8 || Imm > 7)
1693 return Error(IDLoc, "immediate operand value out of range");
1694 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001695 case Mips::ADDIUSP_MM:
1696 Opnd = Inst.getOperand(0);
1697 if (!Opnd.isImm())
1698 return Error(IDLoc, "expected immediate operand kind");
1699 Imm = Opnd.getImm();
1700 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1701 Imm % 4 != 0)
1702 return Error(IDLoc, "immediate operand value out of range");
1703 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001704 case Mips::SLL16_MM:
1705 case Mips::SRL16_MM:
1706 Opnd = Inst.getOperand(2);
1707 if (!Opnd.isImm())
1708 return Error(IDLoc, "expected immediate operand kind");
1709 Imm = Opnd.getImm();
1710 if (Imm < 1 || Imm > 8)
1711 return Error(IDLoc, "immediate operand value out of range");
1712 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001713 case Mips::LI16_MM:
1714 Opnd = Inst.getOperand(1);
1715 if (!Opnd.isImm())
1716 return Error(IDLoc, "expected immediate operand kind");
1717 Imm = Opnd.getImm();
1718 if (Imm < -1 || Imm > 126)
1719 return Error(IDLoc, "immediate operand value out of range");
1720 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001721 case Mips::ADDIUR2_MM:
1722 Opnd = Inst.getOperand(2);
1723 if (!Opnd.isImm())
1724 return Error(IDLoc, "expected immediate operand kind");
1725 Imm = Opnd.getImm();
1726 if (!(Imm == 1 || Imm == -1 ||
1727 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1728 return Error(IDLoc, "immediate operand value out of range");
1729 break;
Zoran Jovanovic42b84442014-10-23 11:13:59 +00001730 case Mips::ADDIUR1SP_MM:
1731 Opnd = Inst.getOperand(1);
1732 if (!Opnd.isImm())
1733 return Error(IDLoc, "expected immediate operand kind");
1734 Imm = Opnd.getImm();
1735 if (OffsetToAlignment(Imm, 4LL))
1736 return Error(IDLoc, "misaligned immediate operand value");
1737 if (Imm < 0 || Imm > 255)
1738 return Error(IDLoc, "immediate operand value out of range");
1739 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001740 case Mips::ANDI16_MM:
1741 Opnd = Inst.getOperand(2);
1742 if (!Opnd.isImm())
1743 return Error(IDLoc, "expected immediate operand kind");
1744 Imm = Opnd.getImm();
1745 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1746 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1747 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1748 return Error(IDLoc, "immediate operand value out of range");
1749 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001750 case Mips::LBU16_MM:
1751 Opnd = Inst.getOperand(2);
1752 if (!Opnd.isImm())
1753 return Error(IDLoc, "expected immediate operand kind");
1754 Imm = Opnd.getImm();
1755 if (Imm < -1 || Imm > 14)
1756 return Error(IDLoc, "immediate operand value out of range");
1757 break;
Zoran Jovanovic7ba636c2015-09-17 10:14:09 +00001758 case Mips::TEQ_MM:
1759 case Mips::TGE_MM:
1760 case Mips::TGEU_MM:
1761 case Mips::TLT_MM:
1762 case Mips::TLTU_MM:
1763 case Mips::TNE_MM:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001764 case Mips::SB16_MM:
1765 Opnd = Inst.getOperand(2);
1766 if (!Opnd.isImm())
1767 return Error(IDLoc, "expected immediate operand kind");
1768 Imm = Opnd.getImm();
1769 if (Imm < 0 || Imm > 15)
1770 return Error(IDLoc, "immediate operand value out of range");
1771 break;
1772 case Mips::LHU16_MM:
1773 case Mips::SH16_MM:
1774 Opnd = Inst.getOperand(2);
1775 if (!Opnd.isImm())
1776 return Error(IDLoc, "expected immediate operand kind");
1777 Imm = Opnd.getImm();
1778 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1779 return Error(IDLoc, "immediate operand value out of range");
1780 break;
1781 case Mips::LW16_MM:
1782 case Mips::SW16_MM:
1783 Opnd = Inst.getOperand(2);
1784 if (!Opnd.isImm())
1785 return Error(IDLoc, "expected immediate operand kind");
1786 Imm = Opnd.getImm();
1787 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1788 return Error(IDLoc, "immediate operand value out of range");
1789 break;
Zoran Jovanovic6e6a2c92015-09-16 09:14:35 +00001790 case Mips::PREFX_MM:
Jozef Kolekab6d1cc2014-12-23 19:55:34 +00001791 case Mips::CACHE:
1792 case Mips::PREF:
1793 Opnd = Inst.getOperand(2);
1794 if (!Opnd.isImm())
1795 return Error(IDLoc, "expected immediate operand kind");
1796 Imm = Opnd.getImm();
1797 if (!isUInt<5>(Imm))
1798 return Error(IDLoc, "immediate operand value out of range");
1799 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001800 case Mips::ADDIUPC_MM:
1801 MCOperand Opnd = Inst.getOperand(1);
1802 if (!Opnd.isImm())
1803 return Error(IDLoc, "expected immediate operand kind");
1804 int Imm = Opnd.getImm();
1805 if ((Imm % 4 != 0) || !isIntN(25, Imm))
1806 return Error(IDLoc, "immediate operand value out of range");
1807 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001808 }
1809 }
1810
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001811 if (needsExpansion(Inst)) {
1812 if (expandInstruction(Inst, IDLoc, Instructions))
1813 return true;
1814 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001815 Instructions.push_back(Inst);
1816
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001817 // If this instruction has a delay slot and .set reorder is active,
1818 // emit a NOP after it.
1819 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
1820 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1821
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001822 if ((Inst.getOpcode() == Mips::JalOneReg ||
1823 Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
1824 isPicAndNotNxxAbi()) {
1825 if (IsCpRestoreSet) {
1826 // We need a NOP between the JALR and the LW:
1827 // If .set reorder has been used, we've already emitted a NOP.
1828 // If .set noreorder has been used, we need to emit a NOP at this point.
1829 if (!AssemblerOptions.back()->isReorder())
1830 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1831
1832 // Load the $gp from the stack.
1833 SmallVector<MCInst, 3> LoadInsts;
1834 createCpRestoreMemOp(true /*IsLoad*/, CpRestoreOffset /*StackOffset*/,
1835 IDLoc, LoadInsts);
1836
1837 for (const MCInst &Inst : LoadInsts)
1838 Instructions.push_back(Inst);
1839
1840 } else
1841 Warning(IDLoc, "no .cprestore used in PIC mode");
1842 }
1843
Jack Carter9e65aa32013-03-22 00:05:30 +00001844 return false;
1845}
1846
Jack Carter30a59822012-10-04 04:03:53 +00001847bool MipsAsmParser::needsExpansion(MCInst &Inst) {
1848
Jack Carterd0bd6422013-04-18 00:41:53 +00001849 switch (Inst.getOpcode()) {
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001850 case Mips::LoadImm32:
1851 case Mips::LoadImm64:
1852 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001853 case Mips::LoadAddrImm64:
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001854 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001855 case Mips::LoadAddrReg64:
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001856 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001857 case Mips::B_MMR6_Pseudo:
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001858 case Mips::LWM_MM:
1859 case Mips::SWM_MM:
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001860 case Mips::JalOneReg:
1861 case Mips::JalTwoReg:
Toma Tabacue1e460d2015-06-11 10:36:10 +00001862 case Mips::BneImm:
1863 case Mips::BeqImm:
Toma Tabacu1a108322015-06-17 13:20:24 +00001864 case Mips::BLT:
1865 case Mips::BLE:
1866 case Mips::BGE:
1867 case Mips::BGT:
1868 case Mips::BLTU:
1869 case Mips::BLEU:
1870 case Mips::BGEU:
1871 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00001872 case Mips::BLTL:
1873 case Mips::BLEL:
1874 case Mips::BGEL:
1875 case Mips::BGTL:
1876 case Mips::BLTUL:
1877 case Mips::BLEUL:
1878 case Mips::BGEUL:
1879 case Mips::BGTUL:
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00001880 case Mips::SDivMacro:
1881 case Mips::UDivMacro:
1882 case Mips::DSDivMacro:
1883 case Mips::DUDivMacro:
Toma Tabacud88d79c2015-06-23 14:39:42 +00001884 case Mips::Ulhu:
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00001885 case Mips::Ulw:
Jack Carterd0bd6422013-04-18 00:41:53 +00001886 return true;
1887 default:
1888 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001889 }
1890}
Jack Carter92995f12012-10-06 00:53:28 +00001891
Matheus Almeida3813d572014-06-19 14:39:14 +00001892bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001893 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001894 switch (Inst.getOpcode()) {
Craig Topperd3c02f12015-01-05 10:15:49 +00001895 default: llvm_unreachable("unimplemented expansion");
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001896 case Mips::LoadImm32:
Toma Tabacu00e98672015-05-01 12:19:27 +00001897 return expandLoadImm(Inst, true, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001898 case Mips::LoadImm64:
Toma Tabacu00e98672015-05-01 12:19:27 +00001899 return expandLoadImm(Inst, false, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001900 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001901 case Mips::LoadAddrImm64:
1902 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1903 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
1904 "expected immediate operand kind");
1905
1906 return expandLoadAddress(
1907 Inst.getOperand(0).getReg(), Mips::NoRegister, Inst.getOperand(1),
1908 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001909 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001910 case Mips::LoadAddrReg64:
1911 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1912 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1913 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
1914 "expected immediate operand kind");
1915
1916 return expandLoadAddress(
1917 Inst.getOperand(0).getReg(), Inst.getOperand(1).getReg(), Inst.getOperand(2),
1918 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc, Instructions);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001919 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001920 case Mips::B_MMR6_Pseudo:
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001921 return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001922 case Mips::SWM_MM:
1923 case Mips::LWM_MM:
1924 return expandLoadStoreMultiple(Inst, IDLoc, Instructions);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001925 case Mips::JalOneReg:
1926 case Mips::JalTwoReg:
1927 return expandJalWithRegs(Inst, IDLoc, Instructions);
Toma Tabacue1e460d2015-06-11 10:36:10 +00001928 case Mips::BneImm:
1929 case Mips::BeqImm:
1930 return expandBranchImm(Inst, IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00001931 case Mips::BLT:
1932 case Mips::BLE:
1933 case Mips::BGE:
1934 case Mips::BGT:
1935 case Mips::BLTU:
1936 case Mips::BLEU:
1937 case Mips::BGEU:
1938 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00001939 case Mips::BLTL:
1940 case Mips::BLEL:
1941 case Mips::BGEL:
1942 case Mips::BGTL:
1943 case Mips::BLTUL:
1944 case Mips::BLEUL:
1945 case Mips::BGEUL:
1946 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00001947 return expandCondBranches(Inst, IDLoc, Instructions);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00001948 case Mips::SDivMacro:
1949 return expandDiv(Inst, IDLoc, Instructions, false, true);
1950 case Mips::DSDivMacro:
1951 return expandDiv(Inst, IDLoc, Instructions, true, true);
1952 case Mips::UDivMacro:
1953 return expandDiv(Inst, IDLoc, Instructions, false, false);
1954 case Mips::DUDivMacro:
1955 return expandDiv(Inst, IDLoc, Instructions, true, false);
Toma Tabacud88d79c2015-06-23 14:39:42 +00001956 case Mips::Ulhu:
1957 return expandUlhu(Inst, IDLoc, Instructions);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00001958 case Mips::Ulw:
1959 return expandUlw(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001960 }
Jack Carter30a59822012-10-04 04:03:53 +00001961}
Jack Carter92995f12012-10-06 00:53:28 +00001962
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001963namespace {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001964void emitRX(unsigned Opcode, unsigned Reg0, MCOperand Op1, SMLoc IDLoc,
Daniel Sanders03f9c012015-07-14 12:24:22 +00001965 SmallVectorImpl<MCInst> &Instructions) {
1966 MCInst tmpInst;
1967 tmpInst.setOpcode(Opcode);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001968 tmpInst.addOperand(MCOperand::createReg(Reg0));
1969 tmpInst.addOperand(Op1);
Daniel Sanders03f9c012015-07-14 12:24:22 +00001970 tmpInst.setLoc(IDLoc);
1971 Instructions.push_back(tmpInst);
1972}
1973
Daniel Sandersf1ae3672015-08-18 09:55:57 +00001974void emitRI(unsigned Opcode, unsigned Reg0, int32_t Imm, SMLoc IDLoc,
Daniel Sanders03f9c012015-07-14 12:24:22 +00001975 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001976 emitRX(Opcode, Reg0, MCOperand::createImm(Imm), IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00001977}
1978
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00001979void emitRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, SMLoc IDLoc,
1980 SmallVectorImpl<MCInst> &Instructions) {
1981 emitRX(Opcode, Reg0, MCOperand::createReg(Reg1), IDLoc, Instructions);
1982}
1983
1984void emitII(unsigned Opcode, int16_t Imm1, int16_t Imm2, SMLoc IDLoc,
1985 SmallVectorImpl<MCInst> &Instructions) {
1986 MCInst tmpInst;
1987 tmpInst.setOpcode(Opcode);
1988 tmpInst.addOperand(MCOperand::createImm(Imm1));
1989 tmpInst.addOperand(MCOperand::createImm(Imm2));
1990 tmpInst.setLoc(IDLoc);
1991 Instructions.push_back(tmpInst);
1992}
1993
1994void emitR(unsigned Opcode, unsigned Reg0, SMLoc IDLoc,
1995 SmallVectorImpl<MCInst> &Instructions) {
1996 MCInst tmpInst;
1997 tmpInst.setOpcode(Opcode);
1998 tmpInst.addOperand(MCOperand::createReg(Reg0));
1999 tmpInst.setLoc(IDLoc);
2000 Instructions.push_back(tmpInst);
2001}
2002
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002003void emitRRX(unsigned Opcode, unsigned Reg0, unsigned Reg1, MCOperand Op2,
Daniel Sanders03f9c012015-07-14 12:24:22 +00002004 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
2005 MCInst tmpInst;
2006 tmpInst.setOpcode(Opcode);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002007 tmpInst.addOperand(MCOperand::createReg(Reg0));
2008 tmpInst.addOperand(MCOperand::createReg(Reg1));
2009 tmpInst.addOperand(Op2);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002010 tmpInst.setLoc(IDLoc);
2011 Instructions.push_back(tmpInst);
2012}
2013
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002014void emitRRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, unsigned Reg2,
Daniel Sanders03f9c012015-07-14 12:24:22 +00002015 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002016 emitRRX(Opcode, Reg0, Reg1, MCOperand::createReg(Reg2), IDLoc,
Daniel Sanders03f9c012015-07-14 12:24:22 +00002017 Instructions);
2018}
2019
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002020void emitRRI(unsigned Opcode, unsigned Reg0, unsigned Reg1, int16_t Imm,
2021 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
2022 emitRRX(Opcode, Reg0, Reg1, MCOperand::createImm(Imm), IDLoc,
2023 Instructions);
2024}
Daniel Sanders03f9c012015-07-14 12:24:22 +00002025
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002026void emitAppropriateDSLL(unsigned DstReg, unsigned SrcReg, int16_t ShiftAmount,
2027 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
2028 if (ShiftAmount >= 32) {
2029 emitRRI(Mips::DSLL32, DstReg, SrcReg, ShiftAmount - 32, IDLoc,
2030 Instructions);
Toma Tabacu7dea2e32015-04-28 14:06:35 +00002031 return;
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002032 }
Toma Tabacu7dea2e32015-04-28 14:06:35 +00002033
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002034 emitRRI(Mips::DSLL, DstReg, SrcReg, ShiftAmount, IDLoc, Instructions);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00002035}
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002036} // end anonymous namespace.
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00002037
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002038bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
2039 SmallVectorImpl<MCInst> &Instructions) {
2040 // Create a JALR instruction which is going to replace the pseudo-JAL.
2041 MCInst JalrInst;
2042 JalrInst.setLoc(IDLoc);
2043 const MCOperand FirstRegOp = Inst.getOperand(0);
2044 const unsigned Opcode = Inst.getOpcode();
2045
2046 if (Opcode == Mips::JalOneReg) {
2047 // jal $rs => jalr $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002048 if (IsCpRestoreSet && inMicroMipsMode()) {
2049 JalrInst.setOpcode(Mips::JALRS16_MM);
2050 JalrInst.addOperand(FirstRegOp);
2051 } else if (inMicroMipsMode()) {
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002052 JalrInst.setOpcode(Mips::JALR16_MM);
2053 JalrInst.addOperand(FirstRegOp);
2054 } else {
2055 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002056 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002057 JalrInst.addOperand(FirstRegOp);
2058 }
2059 } else if (Opcode == Mips::JalTwoReg) {
2060 // jal $rd, $rs => jalr $rd, $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002061 if (IsCpRestoreSet && inMicroMipsMode())
2062 JalrInst.setOpcode(Mips::JALRS_MM);
2063 else
2064 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002065 JalrInst.addOperand(FirstRegOp);
2066 const MCOperand SecondRegOp = Inst.getOperand(1);
2067 JalrInst.addOperand(SecondRegOp);
2068 }
2069 Instructions.push_back(JalrInst);
2070
2071 // If .set reorder is active, emit a NOP after it.
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002072 if (AssemblerOptions.back()->isReorder())
2073 createNop(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc, Instructions);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002074
2075 return false;
2076}
2077
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002078/// Can the value be represented by a unsigned N-bit value and a shift left?
2079template<unsigned N>
2080bool isShiftedUIntAtAnyPosition(uint64_t x) {
2081 unsigned BitNum = findFirstSet(x);
2082
2083 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2084}
2085
2086/// Load (or add) an immediate into a register.
2087///
2088/// @param ImmValue The immediate to load.
2089/// @param DstReg The register that will hold the immediate.
2090/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2091/// for a simple initialization.
2092/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2093/// @param IsAddress True if the immediate represents an address. False if it
2094/// is an integer.
2095/// @param IDLoc Location of the immediate in the source file.
2096/// @param Instructions The instructions emitted by this expansion.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002097bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002098 unsigned SrcReg, bool Is32BitImm,
2099 bool IsAddress, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00002100 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu00e98672015-05-01 12:19:27 +00002101 if (!Is32BitImm && !isGP64bit()) {
2102 Error(IDLoc, "instruction requires a 64-bit architecture");
2103 return true;
2104 }
2105
Daniel Sanders03f9c012015-07-14 12:24:22 +00002106 if (Is32BitImm) {
2107 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2108 // Sign extend up to 64-bit so that the predicates match the hardware
2109 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2110 // true.
2111 ImmValue = SignExtend64<32>(ImmValue);
2112 } else {
2113 Error(IDLoc, "instruction requires a 32-bit immediate");
2114 return true;
2115 }
2116 }
2117
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002118 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2119 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2120
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002121 bool UseSrcReg = false;
2122 if (SrcReg != Mips::NoRegister)
2123 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002124
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002125 unsigned TmpReg = DstReg;
2126 if (UseSrcReg && (DstReg == SrcReg)) {
2127 // At this point we need AT to perform the expansions and we exit if it is
2128 // not available.
2129 unsigned ATReg = getATReg(IDLoc);
2130 if (!ATReg)
2131 return true;
2132 TmpReg = ATReg;
2133 }
2134
Daniel Sanders03f9c012015-07-14 12:24:22 +00002135 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002136 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002137 SrcReg = ZeroReg;
2138
2139 // This doesn't quite follow the usual ABI expectations for N32 but matches
2140 // traditional assembler behaviour. N32 would normally use addiu for both
2141 // integers and addresses.
2142 if (IsAddress && !Is32BitImm) {
2143 emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
2144 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002145 }
2146
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002147 emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
2148 return false;
2149 }
2150
2151 if (isUInt<16>(ImmValue)) {
2152 unsigned TmpReg = DstReg;
2153 if (SrcReg == DstReg) {
2154 TmpReg = getATReg(IDLoc);
2155 if (!TmpReg)
2156 return true;
2157 }
2158
2159 emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002160 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002161 emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2162 return false;
2163 }
2164
2165 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002166 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002167
Toma Tabacu79588102015-04-29 10:19:56 +00002168 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2169 uint16_t Bits15To0 = ImmValue & 0xffff;
2170
Toma Tabacua3d056f2015-05-15 09:42:11 +00002171 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002172 // Traditional behaviour seems to special case this particular value. It's
2173 // not clear why other masks are handled differently.
2174 if (ImmValue == 0xffffffff) {
Daniel Sandersf1ae3672015-08-18 09:55:57 +00002175 emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, Instructions);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002176 emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, Instructions);
2177 if (UseSrcReg)
2178 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2179 return false;
2180 }
2181
2182 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002183 // upper 32 bits.
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002184 emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002185 emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, Instructions);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002186 if (Bits15To0)
2187 emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
2188 if (UseSrcReg)
2189 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2190 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002191 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002192
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002193 emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, Instructions);
2194 if (Bits15To0)
2195 emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002196 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002197 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2198 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002199 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002200
2201 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2202 if (Is32BitImm) {
2203 Error(IDLoc, "instruction requires a 32-bit immediate");
2204 return true;
2205 }
2206
2207 // Traditionally, these immediates are shifted as little as possible and as
2208 // such we align the most significant bit to bit 15 of our temporary.
2209 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2210 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2211 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2212 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
2213 emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, Instructions);
2214 emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, Instructions);
2215
2216 if (UseSrcReg)
2217 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2218
2219 return false;
2220 }
2221
2222 warnIfNoMacro(IDLoc);
2223
2224 // The remaining case is packed with a sequence of dsll and ori with zeros
2225 // being omitted and any neighbouring dsll's being coalesced.
2226 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2227
2228 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2229 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
2230 IDLoc, Instructions))
2231 return false;
2232
2233 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2234 // skip it and defer the shift to the next chunk.
2235 unsigned ShiftCarriedForwards = 16;
2236 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2237 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2238
2239 if (ImmChunk != 0) {
2240 emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
2241 Instructions);
2242 emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, Instructions);
2243 ShiftCarriedForwards = 0;
2244 }
2245
2246 ShiftCarriedForwards += 16;
2247 }
2248 ShiftCarriedForwards -= 16;
2249
2250 // Finish any remaining shifts left by trailing zeros.
2251 if (ShiftCarriedForwards)
2252 emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
2253 Instructions);
2254
2255 if (UseSrcReg)
2256 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2257
Matheus Almeida3813d572014-06-19 14:39:14 +00002258 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002259}
Jack Carter92995f12012-10-06 00:53:28 +00002260
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002261bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
2262 SmallVectorImpl<MCInst> &Instructions) {
2263 const MCOperand &ImmOp = Inst.getOperand(1);
2264 assert(ImmOp.isImm() && "expected immediate operand kind");
2265 const MCOperand &DstRegOp = Inst.getOperand(0);
2266 assert(DstRegOp.isReg() && "expected register operand kind");
2267
2268 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002269 Is32BitImm, false, IDLoc, Instructions))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002270 return true;
2271
2272 return false;
2273}
2274
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002275bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2276 const MCOperand &Offset,
2277 bool Is32BitAddress, SMLoc IDLoc,
2278 SmallVectorImpl<MCInst> &Instructions) {
2279 // la can't produce a usable address when addresses are 64-bit.
2280 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2281 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2282 // We currently can't do this because we depend on the equality
2283 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2284 Error(IDLoc, "la used to load 64-bit address");
2285 // Continue as if we had 'dla' instead.
2286 Is32BitAddress = false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002287 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002288
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002289 // dla requires 64-bit addresses.
2290 if (!Is32BitAddress && !ABI.ArePtrs64bit()) {
2291 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002292 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002293 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002294
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002295 if (!Offset.isImm())
2296 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
2297 Is32BitAddress, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002298
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002299 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
2300 IDLoc, Instructions);
Jack Carter543fdf82012-10-09 23:29:45 +00002301}
2302
Toma Tabacuf712ede2015-06-17 14:31:51 +00002303bool MipsAsmParser::loadAndAddSymbolAddress(
2304 const MCExpr *SymExpr, unsigned DstReg, unsigned SrcReg, bool Is32BitSym,
2305 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002306 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002307
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002308 // FIXME: The way we're handling symbols right now prevents simple expressions
2309 // like foo+8. We'll be able to fix this once our unary operators (%hi
2310 // and similar) are treated as operators rather than as fixup types.
Toma Tabacu674825c2015-06-16 12:16:24 +00002311 const MCSymbolRefExpr *Symbol = cast<MCSymbolRefExpr>(SymExpr);
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002312 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::create(
2313 &Symbol->getSymbol(), MCSymbolRefExpr::VK_Mips_ABS_HI, getContext());
2314 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::create(
2315 &Symbol->getSymbol(), MCSymbolRefExpr::VK_Mips_ABS_LO, getContext());
2316
Toma Tabacufb9d1252015-06-22 12:08:39 +00002317 bool UseSrcReg = SrcReg != Mips::NoRegister;
2318
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002319 // This is the 64-bit symbol address expansion.
2320 if (ABI.ArePtrs64bit() && isGP64bit()) {
2321 // We always need AT for the 64-bit expansion.
2322 // If it is not available we exit.
2323 unsigned ATReg = getATReg(IDLoc);
2324 if (!ATReg)
2325 return true;
2326
2327 const MCSymbolRefExpr *HighestExpr = MCSymbolRefExpr::create(
2328 &Symbol->getSymbol(), MCSymbolRefExpr::VK_Mips_HIGHEST, getContext());
2329 const MCSymbolRefExpr *HigherExpr = MCSymbolRefExpr::create(
2330 &Symbol->getSymbol(), MCSymbolRefExpr::VK_Mips_HIGHER, getContext());
2331
2332 if (UseSrcReg && (DstReg == SrcReg)) {
2333 // If $rs is the same as $rd:
2334 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
2335 // daddiu $at, $at, %higher(sym)
2336 // dsll $at, $at, 16
2337 // daddiu $at, $at, %hi(sym)
2338 // dsll $at, $at, 16
2339 // daddiu $at, $at, %lo(sym)
2340 // daddu $rd, $at, $rd
2341 emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
2342 Instructions);
2343 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HigherExpr),
2344 IDLoc, Instructions);
2345 emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
2346 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
2347 Instructions);
2348 emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
2349 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
2350 Instructions);
2351 emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, Instructions);
2352
2353 return false;
2354 }
2355
2356 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2357 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
2358 // lui $at, %hi(sym)
2359 // daddiu $rd, $rd, %higher(sym)
2360 // daddiu $at, $at, %lo(sym)
2361 // dsll32 $rd, $rd, 0
2362 // daddu $rd, $rd, $at
2363 // (daddu $rd, $rd, $rs)
2364 emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
2365 Instructions);
2366 emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
2367 Instructions);
2368 emitRRX(Mips::DADDiu, DstReg, DstReg, MCOperand::createExpr(HigherExpr),
2369 IDLoc, Instructions);
2370 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
2371 Instructions);
2372 emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, Instructions);
2373 emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, Instructions);
2374 if (UseSrcReg)
2375 emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, Instructions);
2376
2377 return false;
2378 }
2379
2380 // And now, the 32-bit symbol address expansion:
2381 // If $rs is the same as $rd:
2382 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
2383 // ori $at, $at, %lo(sym)
2384 // addu $rd, $at, $rd
2385 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2386 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
2387 // ori $rd, $rd, %lo(sym)
2388 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00002389 unsigned TmpReg = DstReg;
2390 if (UseSrcReg && (DstReg == SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002391 // If $rs is the same as $rd, we need to use AT.
2392 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00002393 unsigned ATReg = getATReg(IDLoc);
2394 if (!ATReg)
2395 return true;
2396 TmpReg = ATReg;
2397 }
2398
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002399 emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, Instructions);
2400 emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr), IDLoc,
2401 Instructions);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002402
Toma Tabacufb9d1252015-06-22 12:08:39 +00002403 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002404 emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2405 else
2406 assert(DstReg == TmpReg);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002407
Toma Tabacu674825c2015-06-16 12:16:24 +00002408 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002409}
2410
NAKAMURA Takumi2bbc90c2015-01-23 01:02:07 +00002411bool MipsAsmParser::expandUncondBranchMMPseudo(
2412 MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00002413 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
2414 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002415
2416 MCOperand Offset = Inst.getOperand(0);
2417 if (Offset.isExpr()) {
2418 Inst.clear();
2419 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002420 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2421 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2422 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002423 } else {
2424 assert(Offset.isImm() && "expected immediate operand kind");
2425 if (isIntN(11, Offset.getImm())) {
2426 // If offset fits into 11 bits then this instruction becomes microMIPS
2427 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00002428 if (inMicroMipsMode())
2429 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002430 } else {
2431 if (!isIntN(17, Offset.getImm()))
2432 Error(IDLoc, "branch target out of range");
2433 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
2434 Error(IDLoc, "branch to misaligned address");
2435 Inst.clear();
2436 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002437 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2438 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2439 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002440 }
2441 }
2442 Instructions.push_back(Inst);
2443
Zoran Jovanovicada70912015-09-07 11:56:37 +00002444 // If .set reorder is active and branch instruction has a delay slot,
2445 // emit a NOP after it.
2446 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
2447 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Toma Tabacu234482a2015-03-16 12:03:39 +00002448 createNop(true, IDLoc, Instructions);
2449
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002450 return false;
2451}
2452
Toma Tabacue1e460d2015-06-11 10:36:10 +00002453bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc,
2454 SmallVectorImpl<MCInst> &Instructions) {
2455 const MCOperand &DstRegOp = Inst.getOperand(0);
2456 assert(DstRegOp.isReg() && "expected register operand kind");
2457
2458 const MCOperand &ImmOp = Inst.getOperand(1);
2459 assert(ImmOp.isImm() && "expected immediate operand kind");
2460
2461 const MCOperand &MemOffsetOp = Inst.getOperand(2);
2462 assert(MemOffsetOp.isImm() && "expected immediate operand kind");
2463
2464 unsigned OpCode = 0;
2465 switch(Inst.getOpcode()) {
2466 case Mips::BneImm:
2467 OpCode = Mips::BNE;
2468 break;
2469 case Mips::BeqImm:
2470 OpCode = Mips::BEQ;
2471 break;
2472 default:
2473 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
2474 break;
2475 }
2476
2477 int64_t ImmValue = ImmOp.getImm();
2478 if (ImmValue == 0) {
2479 MCInst BranchInst;
2480 BranchInst.setOpcode(OpCode);
2481 BranchInst.addOperand(DstRegOp);
2482 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2483 BranchInst.addOperand(MemOffsetOp);
2484 Instructions.push_back(BranchInst);
2485 } else {
2486 warnIfNoMacro(IDLoc);
2487
2488 unsigned ATReg = getATReg(IDLoc);
2489 if (!ATReg)
2490 return true;
2491
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002492 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
2493 IDLoc, Instructions))
Toma Tabacue1e460d2015-06-11 10:36:10 +00002494 return true;
2495
2496 MCInst BranchInst;
2497 BranchInst.setOpcode(OpCode);
2498 BranchInst.addOperand(DstRegOp);
2499 BranchInst.addOperand(MCOperand::createReg(ATReg));
2500 BranchInst.addOperand(MemOffsetOp);
2501 Instructions.push_back(BranchInst);
2502 }
2503 return false;
2504}
2505
Jack Carter9e65aa32013-03-22 00:05:30 +00002506void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00002507 SmallVectorImpl<MCInst> &Instructions,
2508 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002509 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00002510 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00002511 const MCExpr *ExprOffset;
2512 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00002513 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002514 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2515 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002516 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002517 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2518 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002519 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00002520 if (isImmOpnd) {
2521 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
2522 ImmOffset = Inst.getOperand(2).getImm();
2523 LoOffset = ImmOffset & 0x0000ffff;
2524 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00002525 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00002526 if (LoOffset & 0x8000)
2527 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00002528 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00002529 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00002530 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00002531 TempInst.setLoc(IDLoc);
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002532 // These are some of the types of expansions we perform here:
2533 // 1) lw $8, sym => lui $8, %hi(sym)
2534 // lw $8, %lo(sym)($8)
2535 // 2) lw $8, offset($9) => lui $8, %hi(offset)
2536 // add $8, $8, $9
2537 // lw $8, %lo(offset)($9)
2538 // 3) lw $8, offset($8) => lui $at, %hi(offset)
2539 // add $at, $at, $8
2540 // lw $8, %lo(offset)($at)
2541 // 4) sw $8, sym => lui $at, %hi(sym)
2542 // sw $8, %lo(sym)($at)
2543 // 5) sw $8, offset($8) => lui $at, %hi(offset)
2544 // add $at, $at, $8
2545 // sw $8, %lo(offset)($at)
2546 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
2547 // ldc1 $f0, %lo(sym)($at)
2548 //
2549 // For load instructions we can use the destination register as a temporary
2550 // if base and dst are different (examples 1 and 2) and if the base register
2551 // is general purpose otherwise we must use $at (example 6) and error if it's
2552 // not available. For stores we must use $at (examples 4 and 5) because we
2553 // must not clobber the source register setting up the offset.
2554 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
2555 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
2556 unsigned RegClassIDOp0 =
2557 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
2558 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
2559 (RegClassIDOp0 == Mips::GPR64RegClassID);
2560 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00002561 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002562 else {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002563 // At this point we need AT to perform the expansions and we exit if it is
2564 // not available.
Toma Tabacu89a712b2015-04-15 10:48:56 +00002565 TmpRegNum = getATReg(IDLoc);
2566 if (!TmpRegNum)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002567 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002568 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002569
Jack Carter9e65aa32013-03-22 00:05:30 +00002570 TempInst.setOpcode(Mips::LUi);
Jim Grosbache9119e42015-05-13 18:37:00 +00002571 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
Jack Carter9e65aa32013-03-22 00:05:30 +00002572 if (isImmOpnd)
Jim Grosbache9119e42015-05-13 18:37:00 +00002573 TempInst.addOperand(MCOperand::createImm(HiOffset));
Jack Carter9e65aa32013-03-22 00:05:30 +00002574 else {
Toma Tabacu07c97b32015-06-17 10:43:45 +00002575 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
2576 TempInst.addOperand(MCOperand::createExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002577 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002578 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00002579 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00002580 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00002581 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00002582 // Add temp register to base.
Toma Tabacuc6ce0742015-04-08 13:52:41 +00002583 if (BaseRegNum != Mips::ZERO) {
2584 TempInst.setOpcode(Mips::ADDu);
Jim Grosbache9119e42015-05-13 18:37:00 +00002585 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
2586 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
2587 TempInst.addOperand(MCOperand::createReg(BaseRegNum));
Toma Tabacuc6ce0742015-04-08 13:52:41 +00002588 Instructions.push_back(TempInst);
2589 TempInst.clear();
2590 }
Alp Tokercb402912014-01-24 17:20:08 +00002591 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00002592 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00002593 TempInst.setOpcode(Inst.getOpcode());
Jim Grosbache9119e42015-05-13 18:37:00 +00002594 TempInst.addOperand(MCOperand::createReg(RegOpNum));
2595 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
Jack Carter9e65aa32013-03-22 00:05:30 +00002596 if (isImmOpnd)
Jim Grosbache9119e42015-05-13 18:37:00 +00002597 TempInst.addOperand(MCOperand::createImm(LoOffset));
Jack Carter9e65aa32013-03-22 00:05:30 +00002598 else {
Toma Tabacu07c97b32015-06-17 10:43:45 +00002599 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
2600 TempInst.addOperand(MCOperand::createExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002601 }
2602 Instructions.push_back(TempInst);
2603 TempInst.clear();
2604}
2605
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002606bool
2607MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2608 SmallVectorImpl<MCInst> &Instructions) {
2609 unsigned OpNum = Inst.getNumOperands();
2610 unsigned Opcode = Inst.getOpcode();
2611 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2612
2613 assert (Inst.getOperand(OpNum - 1).isImm() &&
2614 Inst.getOperand(OpNum - 2).isReg() &&
2615 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2616
2617 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2618 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
2619 Inst.getOperand(OpNum - 2).getReg() == Mips::SP &&
2620 Inst.getOperand(OpNum - 3).getReg() == Mips::RA)
2621 // It can be implemented as SWM16 or LWM16 instruction.
2622 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2623
2624 Inst.setOpcode(NewOpcode);
2625 Instructions.push_back(Inst);
2626 return false;
2627}
2628
Toma Tabacu1a108322015-06-17 13:20:24 +00002629bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
2630 SmallVectorImpl<MCInst> &Instructions) {
2631 unsigned PseudoOpcode = Inst.getOpcode();
2632 unsigned SrcReg = Inst.getOperand(0).getReg();
2633 unsigned TrgReg = Inst.getOperand(1).getReg();
2634 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
2635
2636 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002637 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00002638
2639 switch (PseudoOpcode) {
2640 case Mips::BLT:
2641 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002642 case Mips::BLTL:
2643 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002644 AcceptsEquality = false;
2645 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002646 IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
2647 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002648 ZeroSrcOpcode = Mips::BGTZ;
2649 ZeroTrgOpcode = Mips::BLTZ;
2650 break;
2651 case Mips::BLE:
2652 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002653 case Mips::BLEL:
2654 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002655 AcceptsEquality = true;
2656 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002657 IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
2658 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002659 ZeroSrcOpcode = Mips::BGEZ;
2660 ZeroTrgOpcode = Mips::BLEZ;
2661 break;
2662 case Mips::BGE:
2663 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002664 case Mips::BGEL:
2665 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002666 AcceptsEquality = true;
2667 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002668 IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
2669 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002670 ZeroSrcOpcode = Mips::BLEZ;
2671 ZeroTrgOpcode = Mips::BGEZ;
2672 break;
2673 case Mips::BGT:
2674 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002675 case Mips::BGTL:
2676 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002677 AcceptsEquality = false;
2678 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002679 IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
2680 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002681 ZeroSrcOpcode = Mips::BLTZ;
2682 ZeroTrgOpcode = Mips::BGTZ;
2683 break;
2684 default:
2685 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2686 }
2687
2688 MCInst BranchInst;
2689 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
2690 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
2691 if (IsSrcRegZero && IsTrgRegZero) {
2692 // FIXME: All of these Opcode-specific if's are needed for compatibility
2693 // with GAS' behaviour. However, they may not generate the most efficient
2694 // code in some circumstances.
2695 if (PseudoOpcode == Mips::BLT) {
2696 BranchInst.setOpcode(Mips::BLTZ);
2697 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2698 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2699 Instructions.push_back(BranchInst);
2700 return false;
2701 }
2702 if (PseudoOpcode == Mips::BLE) {
2703 BranchInst.setOpcode(Mips::BLEZ);
2704 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2705 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2706 Instructions.push_back(BranchInst);
2707 Warning(IDLoc, "branch is always taken");
2708 return false;
2709 }
2710 if (PseudoOpcode == Mips::BGE) {
2711 BranchInst.setOpcode(Mips::BGEZ);
2712 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2713 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2714 Instructions.push_back(BranchInst);
2715 Warning(IDLoc, "branch is always taken");
2716 return false;
2717 }
2718 if (PseudoOpcode == Mips::BGT) {
2719 BranchInst.setOpcode(Mips::BGTZ);
2720 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2721 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2722 Instructions.push_back(BranchInst);
2723 return false;
2724 }
2725 if (PseudoOpcode == Mips::BGTU) {
2726 BranchInst.setOpcode(Mips::BNE);
2727 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2728 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2729 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2730 Instructions.push_back(BranchInst);
2731 return false;
2732 }
2733 if (AcceptsEquality) {
2734 // If both registers are $0 and the pseudo-branch accepts equality, it
2735 // will always be taken, so we emit an unconditional branch.
2736 BranchInst.setOpcode(Mips::BEQ);
2737 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2738 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2739 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2740 Instructions.push_back(BranchInst);
2741 Warning(IDLoc, "branch is always taken");
2742 return false;
2743 }
2744 // If both registers are $0 and the pseudo-branch does not accept
2745 // equality, it will never be taken, so we don't have to emit anything.
2746 return false;
2747 }
2748 if (IsSrcRegZero || IsTrgRegZero) {
2749 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
2750 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
2751 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
2752 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
2753 // the pseudo-branch will never be taken, so we don't emit anything.
2754 // This only applies to unsigned pseudo-branches.
2755 return false;
2756 }
2757 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
2758 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
2759 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
2760 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
2761 // the pseudo-branch will always be taken, so we emit an unconditional
2762 // branch.
2763 // This only applies to unsigned pseudo-branches.
2764 BranchInst.setOpcode(Mips::BEQ);
2765 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2766 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2767 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2768 Instructions.push_back(BranchInst);
2769 Warning(IDLoc, "branch is always taken");
2770 return false;
2771 }
2772 if (IsUnsigned) {
2773 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
2774 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
2775 // the pseudo-branch will be taken only when the non-zero register is
2776 // different from 0, so we emit a BNEZ.
2777 //
2778 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
2779 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
2780 // the pseudo-branch will be taken only when the non-zero register is
2781 // equal to 0, so we emit a BEQZ.
2782 //
2783 // Because only BLEU and BGEU branch on equality, we can use the
2784 // AcceptsEquality variable to decide when to emit the BEQZ.
2785 BranchInst.setOpcode(AcceptsEquality ? Mips::BEQ : Mips::BNE);
2786 BranchInst.addOperand(
2787 MCOperand::createReg(IsSrcRegZero ? TrgReg : SrcReg));
2788 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2789 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2790 Instructions.push_back(BranchInst);
2791 return false;
2792 }
2793 // If we have a signed pseudo-branch and one of the registers is $0,
2794 // we can use an appropriate compare-to-zero branch. We select which one
2795 // to use in the switch statement above.
2796 BranchInst.setOpcode(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode);
2797 BranchInst.addOperand(MCOperand::createReg(IsSrcRegZero ? TrgReg : SrcReg));
2798 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2799 Instructions.push_back(BranchInst);
2800 return false;
2801 }
2802
2803 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
2804 // expansions. If it is not available, we return.
2805 unsigned ATRegNum = getATReg(IDLoc);
2806 if (!ATRegNum)
2807 return true;
2808
2809 warnIfNoMacro(IDLoc);
2810
2811 // SLT fits well with 2 of our 4 pseudo-branches:
2812 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
2813 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
2814 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
2815 // This is accomplished by using a BNEZ with the result of the SLT.
2816 //
2817 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
2818 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
2819 // Because only BGE and BLE branch on equality, we can use the
2820 // AcceptsEquality variable to decide when to emit the BEQZ.
2821 // Note that the order of the SLT arguments doesn't change between
2822 // opposites.
2823 //
2824 // The same applies to the unsigned variants, except that SLTu is used
2825 // instead of SLT.
2826 MCInst SetInst;
2827 SetInst.setOpcode(IsUnsigned ? Mips::SLTu : Mips::SLT);
2828 SetInst.addOperand(MCOperand::createReg(ATRegNum));
2829 SetInst.addOperand(MCOperand::createReg(ReverseOrderSLT ? TrgReg : SrcReg));
2830 SetInst.addOperand(MCOperand::createReg(ReverseOrderSLT ? SrcReg : TrgReg));
2831 Instructions.push_back(SetInst);
2832
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002833 if (!IsLikely)
2834 BranchInst.setOpcode(AcceptsEquality ? Mips::BEQ : Mips::BNE);
2835 else
2836 BranchInst.setOpcode(AcceptsEquality ? Mips::BEQL : Mips::BNEL);
Toma Tabacu1a108322015-06-17 13:20:24 +00002837 BranchInst.addOperand(MCOperand::createReg(ATRegNum));
2838 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2839 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2840 Instructions.push_back(BranchInst);
2841 return false;
2842}
2843
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002844bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc,
2845 SmallVectorImpl<MCInst> &Instructions,
2846 const bool IsMips64, const bool Signed) {
2847 if (hasMips32r6()) {
2848 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
2849 return false;
2850 }
2851
2852 warnIfNoMacro(IDLoc);
2853
2854 const MCOperand &RsRegOp = Inst.getOperand(0);
2855 assert(RsRegOp.isReg() && "expected register operand kind");
2856 unsigned RsReg = RsRegOp.getReg();
2857
2858 const MCOperand &RtRegOp = Inst.getOperand(1);
2859 assert(RtRegOp.isReg() && "expected register operand kind");
2860 unsigned RtReg = RtRegOp.getReg();
2861 unsigned DivOp;
2862 unsigned ZeroReg;
2863
2864 if (IsMips64) {
2865 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
2866 ZeroReg = Mips::ZERO_64;
2867 } else {
2868 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
2869 ZeroReg = Mips::ZERO;
2870 }
2871
2872 bool UseTraps = useTraps();
2873
2874 if (RsReg == Mips::ZERO || RsReg == Mips::ZERO_64) {
2875 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)
2876 Warning(IDLoc, "dividing zero by zero");
2877 if (IsMips64) {
2878 if (Signed && (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)) {
2879 if (UseTraps) {
2880 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2881 return false;
2882 }
2883
2884 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2885 return false;
2886 }
2887 } else {
2888 emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
2889 return false;
2890 }
2891 }
2892
2893 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
2894 Warning(IDLoc, "division by zero");
2895 if (Signed) {
2896 if (UseTraps) {
2897 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2898 return false;
2899 }
2900
2901 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2902 return false;
2903 }
2904 }
2905
2906 // FIXME: The values for these two BranchTarget variables may be different in
2907 // micromips. These magic numbers need to be removed.
2908 unsigned BranchTargetNoTraps;
2909 unsigned BranchTarget;
2910
2911 if (UseTraps) {
2912 BranchTarget = IsMips64 ? 12 : 8;
2913 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2914 } else {
2915 BranchTarget = IsMips64 ? 20 : 16;
2916 BranchTargetNoTraps = 8;
2917 // Branch to the li instruction.
2918 emitRRI(Mips::BNE, RtReg, ZeroReg, BranchTargetNoTraps, IDLoc,
2919 Instructions);
2920 }
2921
2922 emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
2923
2924 if (!UseTraps)
2925 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2926
2927 if (!Signed) {
2928 emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
2929 return false;
2930 }
2931
2932 unsigned ATReg = getATReg(IDLoc);
2933 if (!ATReg)
2934 return true;
2935
2936 emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, Instructions);
2937 if (IsMips64) {
2938 // Branch to the mflo instruction.
2939 emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
2940 emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, Instructions);
2941 emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, Instructions);
2942 } else {
2943 // Branch to the mflo instruction.
2944 emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
2945 emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, Instructions);
2946 }
2947
2948 if (UseTraps)
2949 emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, Instructions);
2950 else {
2951 // Branch to the mflo instruction.
2952 emitRRI(Mips::BNE, RsReg, ATReg, BranchTargetNoTraps, IDLoc, Instructions);
2953 emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, Instructions);
2954 emitII(Mips::BREAK, 0x6, 0, IDLoc, Instructions);
2955 }
2956 emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
2957 return false;
2958}
2959
Toma Tabacud88d79c2015-06-23 14:39:42 +00002960bool MipsAsmParser::expandUlhu(MCInst &Inst, SMLoc IDLoc,
2961 SmallVectorImpl<MCInst> &Instructions) {
2962 if (hasMips32r6() || hasMips64r6()) {
2963 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
2964 return false;
2965 }
2966
2967 warnIfNoMacro(IDLoc);
2968
2969 const MCOperand &DstRegOp = Inst.getOperand(0);
2970 assert(DstRegOp.isReg() && "expected register operand kind");
2971
2972 const MCOperand &SrcRegOp = Inst.getOperand(1);
2973 assert(SrcRegOp.isReg() && "expected register operand kind");
2974
2975 const MCOperand &OffsetImmOp = Inst.getOperand(2);
2976 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
2977
2978 unsigned DstReg = DstRegOp.getReg();
2979 unsigned SrcReg = SrcRegOp.getReg();
2980 int64_t OffsetValue = OffsetImmOp.getImm();
2981
2982 // NOTE: We always need AT for ULHU, as it is always used as the source
2983 // register for one of the LBu's.
2984 unsigned ATReg = getATReg(IDLoc);
2985 if (!ATReg)
2986 return true;
2987
2988 // When the value of offset+1 does not fit in 16 bits, we have to load the
2989 // offset in AT, (D)ADDu the original source register (if there was one), and
2990 // then use AT as the source register for the 2 generated LBu's.
2991 bool LoadedOffsetInAT = false;
2992 if (!isInt<16>(OffsetValue + 1) || !isInt<16>(OffsetValue)) {
2993 LoadedOffsetInAT = true;
2994
2995 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002996 true, IDLoc, Instructions))
Toma Tabacud88d79c2015-06-23 14:39:42 +00002997 return true;
2998
2999 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3000 // because it will make our output more similar to GAS'. For example,
3001 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3002 // instead of just an "ori $1, $9, 32768".
3003 // NOTE: If there is no source register specified in the ULHU, the parser
3004 // will interpret it as $0.
3005 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
3006 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
3007 }
3008
3009 unsigned FirstLbuDstReg = LoadedOffsetInAT ? DstReg : ATReg;
3010 unsigned SecondLbuDstReg = LoadedOffsetInAT ? ATReg : DstReg;
3011 unsigned LbuSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3012
3013 int64_t FirstLbuOffset = 0, SecondLbuOffset = 0;
3014 if (isLittle()) {
3015 FirstLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3016 SecondLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3017 } else {
3018 FirstLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3019 SecondLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3020 }
3021
3022 unsigned SllReg = LoadedOffsetInAT ? DstReg : ATReg;
3023
3024 MCInst TmpInst;
3025 TmpInst.setOpcode(Mips::LBu);
3026 TmpInst.addOperand(MCOperand::createReg(FirstLbuDstReg));
3027 TmpInst.addOperand(MCOperand::createReg(LbuSrcReg));
3028 TmpInst.addOperand(MCOperand::createImm(FirstLbuOffset));
3029 Instructions.push_back(TmpInst);
3030
3031 TmpInst.clear();
3032 TmpInst.setOpcode(Mips::LBu);
3033 TmpInst.addOperand(MCOperand::createReg(SecondLbuDstReg));
3034 TmpInst.addOperand(MCOperand::createReg(LbuSrcReg));
3035 TmpInst.addOperand(MCOperand::createImm(SecondLbuOffset));
3036 Instructions.push_back(TmpInst);
3037
3038 TmpInst.clear();
3039 TmpInst.setOpcode(Mips::SLL);
3040 TmpInst.addOperand(MCOperand::createReg(SllReg));
3041 TmpInst.addOperand(MCOperand::createReg(SllReg));
3042 TmpInst.addOperand(MCOperand::createImm(8));
3043 Instructions.push_back(TmpInst);
3044
3045 TmpInst.clear();
3046 TmpInst.setOpcode(Mips::OR);
3047 TmpInst.addOperand(MCOperand::createReg(DstReg));
3048 TmpInst.addOperand(MCOperand::createReg(DstReg));
3049 TmpInst.addOperand(MCOperand::createReg(ATReg));
3050 Instructions.push_back(TmpInst);
3051
3052 return false;
3053}
3054
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003055bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc,
3056 SmallVectorImpl<MCInst> &Instructions) {
3057 if (hasMips32r6() || hasMips64r6()) {
3058 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3059 return false;
3060 }
3061
3062 const MCOperand &DstRegOp = Inst.getOperand(0);
3063 assert(DstRegOp.isReg() && "expected register operand kind");
3064
3065 const MCOperand &SrcRegOp = Inst.getOperand(1);
3066 assert(SrcRegOp.isReg() && "expected register operand kind");
3067
3068 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3069 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3070
3071 unsigned SrcReg = SrcRegOp.getReg();
3072 int64_t OffsetValue = OffsetImmOp.getImm();
3073 unsigned ATReg = 0;
3074
3075 // When the value of offset+3 does not fit in 16 bits, we have to load the
3076 // offset in AT, (D)ADDu the original source register (if there was one), and
3077 // then use AT as the source register for the generated LWL and LWR.
3078 bool LoadedOffsetInAT = false;
3079 if (!isInt<16>(OffsetValue + 3) || !isInt<16>(OffsetValue)) {
3080 ATReg = getATReg(IDLoc);
3081 if (!ATReg)
3082 return true;
3083 LoadedOffsetInAT = true;
3084
3085 warnIfNoMacro(IDLoc);
3086
3087 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003088 true, IDLoc, Instructions))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003089 return true;
3090
3091 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3092 // because it will make our output more similar to GAS'. For example,
3093 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3094 // instead of just an "ori $1, $9, 32768".
3095 // NOTE: If there is no source register specified in the ULW, the parser
3096 // will interpret it as $0.
3097 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
3098 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
3099 }
3100
3101 unsigned FinalSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3102 int64_t LeftLoadOffset = 0, RightLoadOffset = 0;
3103 if (isLittle()) {
3104 LeftLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3105 RightLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3106 } else {
3107 LeftLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3108 RightLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3109 }
3110
3111 MCInst LeftLoadInst;
3112 LeftLoadInst.setOpcode(Mips::LWL);
3113 LeftLoadInst.addOperand(DstRegOp);
3114 LeftLoadInst.addOperand(MCOperand::createReg(FinalSrcReg));
3115 LeftLoadInst.addOperand(MCOperand::createImm(LeftLoadOffset));
3116 Instructions.push_back(LeftLoadInst);
3117
3118 MCInst RightLoadInst;
3119 RightLoadInst.setOpcode(Mips::LWR);
3120 RightLoadInst.addOperand(DstRegOp);
3121 RightLoadInst.addOperand(MCOperand::createReg(FinalSrcReg));
3122 RightLoadInst.addOperand(MCOperand::createImm(RightLoadOffset ));
3123 Instructions.push_back(RightLoadInst);
3124
3125 return false;
3126}
3127
Toma Tabacu234482a2015-03-16 12:03:39 +00003128void MipsAsmParser::createNop(bool hasShortDelaySlot, SMLoc IDLoc,
3129 SmallVectorImpl<MCInst> &Instructions) {
3130 MCInst NopInst;
3131 if (hasShortDelaySlot) {
3132 NopInst.setOpcode(Mips::MOVE16_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00003133 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
3134 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
Toma Tabacu234482a2015-03-16 12:03:39 +00003135 } else {
3136 NopInst.setOpcode(Mips::SLL);
Jim Grosbache9119e42015-05-13 18:37:00 +00003137 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
3138 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
3139 NopInst.addOperand(MCOperand::createImm(0));
Toma Tabacu234482a2015-03-16 12:03:39 +00003140 }
3141 Instructions.push_back(NopInst);
3142}
3143
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003144void MipsAsmParser::createAddu(unsigned DstReg, unsigned SrcReg,
Toma Tabacu0b3e9782015-06-23 14:00:54 +00003145 unsigned TrgReg, bool Is64Bit,
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003146 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanders03f9c012015-07-14 12:24:22 +00003147 emitRRR(Is64Bit ? Mips::DADDu : Mips::ADDu, DstReg, SrcReg, TrgReg, SMLoc(),
3148 Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003149}
3150
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003151void MipsAsmParser::createCpRestoreMemOp(
3152 bool IsLoad, int StackOffset, SMLoc IDLoc,
3153 SmallVectorImpl<MCInst> &Instructions) {
3154 MCInst MemInst;
3155 MemInst.setOpcode(IsLoad ? Mips::LW : Mips::SW);
3156 MemInst.addOperand(MCOperand::createReg(Mips::GP));
3157 MemInst.addOperand(MCOperand::createReg(Mips::SP));
3158 MemInst.addOperand(MCOperand::createImm(StackOffset));
3159
3160 // If the offset can not fit into 16 bits, we need to expand.
3161 if (!isInt<16>(StackOffset))
3162 expandMemInst(MemInst, IDLoc, Instructions, IsLoad, true /*HasImmOpnd*/);
3163 else
3164 Instructions.push_back(MemInst);
3165}
3166
Matheus Almeida595fcab2014-06-11 15:05:56 +00003167unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
3168 // As described by the Mips32r2 spec, the registers Rd and Rs for
3169 // jalr.hb must be different.
3170 unsigned Opcode = Inst.getOpcode();
3171
3172 if (Opcode == Mips::JALR_HB &&
3173 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
3174 return Match_RequiresDifferentSrcAndDst;
3175
3176 return Match_Success;
3177}
3178
David Blaikie960ea3f2014-06-08 16:18:35 +00003179bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3180 OperandVector &Operands,
3181 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003182 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00003183 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00003184
Jack Carterb4dbc172012-09-05 23:34:03 +00003185 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00003186 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00003187 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003188 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00003189
3190 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003191 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003192 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00003193 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00003194 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00003195 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00003196 return false;
3197 }
3198 case Match_MissingFeature:
3199 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
3200 return true;
3201 case Match_InvalidOperand: {
3202 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00003203 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003204 if (ErrorInfo >= Operands.size())
3205 return Error(IDLoc, "too few operands for instruction");
3206
David Blaikie960ea3f2014-06-08 16:18:35 +00003207 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00003208 if (ErrorLoc == SMLoc())
3209 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00003210 }
3211
3212 return Error(ErrorLoc, "invalid operand for instruction");
3213 }
3214 case Match_MnemonicFail:
3215 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00003216 case Match_RequiresDifferentSrcAndDst:
3217 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00003218 }
Craig Topper589ceee2015-01-03 08:16:34 +00003219
3220 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00003221}
3222
Toma Tabacud9d344b2015-04-27 14:05:04 +00003223void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
3224 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
3225 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
3226 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003227}
3228
Toma Tabacu81496c12015-05-20 08:54:45 +00003229void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
3230 if (!AssemblerOptions.back()->isMacro())
3231 Warning(Loc, "macro instruction expanded into multiple instructions");
3232}
3233
Daniel Sandersef638fe2014-10-03 15:37:37 +00003234void
3235MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
3236 SMRange Range, bool ShowColors) {
3237 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00003238 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00003239 ShowColors);
3240}
3241
Jack Carter1ac53222013-02-20 23:11:17 +00003242int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003243 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003244
Vladimir Medic4c299852013-11-06 11:27:05 +00003245 CC = StringSwitch<unsigned>(Name)
3246 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003247 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00003248 .Case("a0", 4)
3249 .Case("a1", 5)
3250 .Case("a2", 6)
3251 .Case("a3", 7)
3252 .Case("v0", 2)
3253 .Case("v1", 3)
3254 .Case("s0", 16)
3255 .Case("s1", 17)
3256 .Case("s2", 18)
3257 .Case("s3", 19)
3258 .Case("s4", 20)
3259 .Case("s5", 21)
3260 .Case("s6", 22)
3261 .Case("s7", 23)
3262 .Case("k0", 26)
3263 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003264 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00003265 .Case("sp", 29)
3266 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003267 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00003268 .Case("ra", 31)
3269 .Case("t0", 8)
3270 .Case("t1", 9)
3271 .Case("t2", 10)
3272 .Case("t3", 11)
3273 .Case("t4", 12)
3274 .Case("t5", 13)
3275 .Case("t6", 14)
3276 .Case("t7", 15)
3277 .Case("t8", 24)
3278 .Case("t9", 25)
3279 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003280
Toma Tabacufda445c2014-09-15 15:33:01 +00003281 if (!(isABI_N32() || isABI_N64()))
3282 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003283
Daniel Sandersef638fe2014-10-03 15:37:37 +00003284 if (12 <= CC && CC <= 15) {
3285 // Name is one of t4-t7
3286 AsmToken RegTok = getLexer().peekTok();
3287 SMRange RegRange = RegTok.getLocRange();
3288
3289 StringRef FixedName = StringSwitch<StringRef>(Name)
3290 .Case("t4", "t0")
3291 .Case("t5", "t1")
3292 .Case("t6", "t2")
3293 .Case("t7", "t3")
3294 .Default("");
3295 assert(FixedName != "" && "Register name is not one of t4-t7.");
3296
3297 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
3298 "Did you mean $" + FixedName + "?", RegRange);
3299 }
3300
Toma Tabacufda445c2014-09-15 15:33:01 +00003301 // Although SGI documentation just cuts out t0-t3 for n32/n64,
3302 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
3303 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
3304 if (8 <= CC && CC <= 11)
3305 CC += 4;
3306
3307 if (CC == -1)
3308 CC = StringSwitch<unsigned>(Name)
3309 .Case("a4", 8)
3310 .Case("a5", 9)
3311 .Case("a6", 10)
3312 .Case("a7", 11)
3313 .Case("kt0", 26)
3314 .Case("kt1", 27)
3315 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003316
3317 return CC;
3318}
Jack Carterd0bd6422013-04-18 00:41:53 +00003319
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003320int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
3321 int CC;
3322
3323 CC = StringSwitch<unsigned>(Name)
3324 .Case("hwr_cpunum", 0)
3325 .Case("hwr_synci_step", 1)
3326 .Case("hwr_cc", 2)
3327 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00003328 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003329 .Default(-1);
3330
3331 return CC;
3332}
3333
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003334int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003335
Jack Cartera63b16a2012-09-07 00:23:42 +00003336 if (Name[0] == 'f') {
3337 StringRef NumString = Name.substr(1);
3338 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003339 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003340 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003341 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00003342 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003343 return IntVal;
3344 }
3345 return -1;
3346}
Jack Cartera63b16a2012-09-07 00:23:42 +00003347
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003348int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
3349
3350 if (Name.startswith("fcc")) {
3351 StringRef NumString = Name.substr(3);
3352 unsigned IntVal;
3353 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003354 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003355 if (IntVal > 7) // There are only 8 fcc registers.
3356 return -1;
3357 return IntVal;
3358 }
3359 return -1;
3360}
3361
3362int MipsAsmParser::matchACRegisterName(StringRef Name) {
3363
Akira Hatanaka274d24c2013-08-14 01:15:52 +00003364 if (Name.startswith("ac")) {
3365 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003366 unsigned IntVal;
3367 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003368 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003369 if (IntVal > 3) // There are only 3 acc registers.
3370 return -1;
3371 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00003372 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003373 return -1;
3374}
Jack Carterd0bd6422013-04-18 00:41:53 +00003375
Jack Carter5dc8ac92013-09-25 23:50:44 +00003376int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
3377 unsigned IntVal;
3378
3379 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
3380 return -1;
3381
3382 if (IntVal > 31)
3383 return -1;
3384
3385 return IntVal;
3386}
3387
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003388int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
3389 int CC;
3390
3391 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00003392 .Case("msair", 0)
3393 .Case("msacsr", 1)
3394 .Case("msaaccess", 2)
3395 .Case("msasave", 3)
3396 .Case("msamodify", 4)
3397 .Case("msarequest", 5)
3398 .Case("msamap", 6)
3399 .Case("msaunmap", 7)
3400 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003401
3402 return CC;
3403}
3404
Toma Tabacu89a712b2015-04-15 10:48:56 +00003405unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00003406 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00003407 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00003408 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00003409 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00003410 return 0;
3411 }
3412 unsigned AT = getReg(
3413 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00003414 return AT;
3415}
Jack Carter0b744b32012-10-04 02:29:46 +00003416
Jack Carterd0bd6422013-04-18 00:41:53 +00003417unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00003418 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00003419}
3420
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003421unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003422 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00003423 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003424}
3425
Jack Carter873c7242013-01-12 01:03:14 +00003426int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003427 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00003428 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00003429 return -1;
3430
Jack Carter873c7242013-01-12 01:03:14 +00003431 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00003432}
3433
Toma Tabacu13964452014-09-04 13:23:44 +00003434bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003435 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00003436 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003437
Jack Carter30a59822012-10-04 04:03:53 +00003438 // Check if the current operand has a custom associated parser, if so, try to
3439 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00003440 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3441 if (ResTy == MatchOperand_Success)
3442 return false;
3443 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3444 // there was a match, but an error occurred, in which case, just return that
3445 // the operand parsing failed.
3446 if (ResTy == MatchOperand_ParseFail)
3447 return true;
3448
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003449 DEBUG(dbgs() << ".. Generic Parser\n");
3450
Jack Carterb4dbc172012-09-05 23:34:03 +00003451 switch (getLexer().getKind()) {
3452 default:
3453 Error(Parser.getTok().getLoc(), "unexpected token in operand");
3454 return true;
3455 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003456 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00003457 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00003458
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003459 // Almost all registers have been parsed by custom parsers. There is only
3460 // one exception to this. $zero (and it's alias $0) will reach this point
3461 // for div, divu, and similar instructions because it is not an operand
3462 // to the instruction definition but an explicit register. Special case
3463 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00003464 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00003465 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003466
Jack Carterd0bd6422013-04-18 00:41:53 +00003467 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00003468 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003469 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00003470 return true;
3471
Jack Carter873c7242013-01-12 01:03:14 +00003472 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00003473 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00003474 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00003475 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003476 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00003477
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003478 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003479 return false;
3480 }
Vladimir Medic4c299852013-11-06 11:27:05 +00003481 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00003482 case AsmToken::LParen:
3483 case AsmToken::Minus:
3484 case AsmToken::Plus:
3485 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00003486 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00003487 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003488 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00003489 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003490 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00003491 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00003492 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003493 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003494 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003495 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00003496 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00003497 return true;
3498
Jack Carter873c7242013-01-12 01:03:14 +00003499 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3500
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003501 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00003502 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003503 } // case AsmToken::Percent
3504 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00003505 return true;
3506}
3507
Vladimir Medic4c299852013-11-06 11:27:05 +00003508const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00003509 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00003510 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00003511 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00003512 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00003513 // It's a constant, evaluate reloc value.
3514 int16_t Val;
3515 switch (getVariantKind(RelocStr)) {
3516 case MCSymbolRefExpr::VK_Mips_ABS_LO:
3517 // Get the 1st 16-bits.
3518 Val = MCE->getValue() & 0xffff;
3519 break;
3520 case MCSymbolRefExpr::VK_Mips_ABS_HI:
3521 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
3522 // 16 bits being negative.
3523 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
3524 break;
3525 case MCSymbolRefExpr::VK_Mips_HIGHER:
3526 // Get the 3rd 16-bits.
3527 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
3528 break;
3529 case MCSymbolRefExpr::VK_Mips_HIGHEST:
3530 // Get the 4th 16-bits.
3531 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
3532 break;
3533 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00003534 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00003535 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00003536 return MCConstantExpr::create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00003537 }
3538
Jack Carterb5cf5902013-04-17 00:18:04 +00003539 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003540 // It's a symbol, create a symbolic expression from the symbol.
Toma Tabacu07c97b32015-06-17 10:43:45 +00003541 const MCSymbol *Symbol = &MSRE->getSymbol();
Jack Carterb5cf5902013-04-17 00:18:04 +00003542 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003543 Res = MCSymbolRefExpr::create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003544 return Res;
3545 }
3546
3547 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00003548 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
3549
Sasa Stankovic06c47802014-04-03 10:37:45 +00003550 // Try to create target expression.
3551 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
Jim Grosbach13760bd2015-05-30 01:25:56 +00003552 return MipsMCExpr::create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00003553
Jack Carterd0bd6422013-04-18 00:41:53 +00003554 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
3555 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003556 Res = MCBinaryExpr::create(BE->getOpcode(), LExp, RExp, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003557 return Res;
3558 }
3559
3560 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003561 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003562 Res = MCUnaryExpr::create(UN->getOpcode(), UnExp, getContext());
Jack Carterd0bd6422013-04-18 00:41:53 +00003563 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00003564 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003565 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00003566 return Expr;
3567}
3568
3569bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
3570
3571 switch (Expr->getKind()) {
3572 case MCExpr::Constant:
3573 return true;
3574 case MCExpr::SymbolRef:
3575 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
3576 case MCExpr::Binary:
3577 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
3578 if (!isEvaluated(BE->getLHS()))
3579 return false;
3580 return isEvaluated(BE->getRHS());
3581 }
3582 case MCExpr::Unary:
3583 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00003584 case MCExpr::Target:
3585 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003586 }
Jack Carterb5cf5902013-04-17 00:18:04 +00003587 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00003588}
Jack Carterd0bd6422013-04-18 00:41:53 +00003589
Jack Carterb5cf5902013-04-17 00:18:04 +00003590bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003591 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00003592 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00003593 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00003594 if (Tok.isNot(AsmToken::Identifier))
3595 return true;
3596
Yaron Keren075759a2015-03-30 15:42:36 +00003597 std::string Str = Tok.getIdentifier();
Jack Carterb5cf5902013-04-17 00:18:04 +00003598
Jack Carterd0bd6422013-04-18 00:41:53 +00003599 Parser.Lex(); // Eat the identifier.
3600 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003601 const MCExpr *IdVal;
3602 SMLoc EndLoc;
3603
3604 if (getLexer().getKind() == AsmToken::LParen) {
3605 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003606 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003607 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003608 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003609 const AsmToken &nextTok = Parser.getTok();
3610 if (nextTok.isNot(AsmToken::Identifier))
3611 return true;
3612 Str += "(%";
3613 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00003614 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00003615 if (getLexer().getKind() != AsmToken::LParen)
3616 return true;
3617 } else
3618 break;
3619 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003620 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00003621 return true;
3622
3623 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00003624 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003625
3626 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00003627 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003628
Jack Carterd0bd6422013-04-18 00:41:53 +00003629 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00003630 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003631}
3632
Jack Carterb4dbc172012-09-05 23:34:03 +00003633bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
3634 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003635 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00003636 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003637 if (ResTy == MatchOperand_Success) {
3638 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00003639 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003640 StartLoc = Operand.getStartLoc();
3641 EndLoc = Operand.getEndLoc();
3642
3643 // AFAIK, we only support numeric registers and named GPR's in CFI
3644 // directives.
3645 // Don't worry about eating tokens before failing. Using an unrecognised
3646 // register is a parse error.
3647 if (Operand.isGPRAsmReg()) {
3648 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003649 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003650 }
3651
3652 return (RegNo == (unsigned)-1);
3653 }
3654
3655 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00003656 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00003657}
3658
Jack Carterb5cf5902013-04-17 00:18:04 +00003659bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003660 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00003661 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00003662 bool Result = true;
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003663 unsigned NumOfLParen = 0;
Jack Carterb5cf5902013-04-17 00:18:04 +00003664
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003665 while (getLexer().getKind() == AsmToken::LParen) {
Jack Carterb5cf5902013-04-17 00:18:04 +00003666 Parser.Lex();
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003667 ++NumOfLParen;
3668 }
Jack Carter873c7242013-01-12 01:03:14 +00003669
Jack Carterd0bd6422013-04-18 00:41:53 +00003670 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00003671 default:
3672 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00003673 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00003674 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00003675 case AsmToken::Integer:
3676 case AsmToken::Minus:
3677 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00003678 if (isParenExpr)
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003679 Result = getParser().parseParenExprOfDepth(NumOfLParen, Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00003680 else
3681 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00003682 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00003683 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003684 break;
Jack Carter873c7242013-01-12 01:03:14 +00003685 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00003686 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00003687 }
Jack Carterb5cf5902013-04-17 00:18:04 +00003688 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003689}
3690
David Blaikie960ea3f2014-06-08 16:18:35 +00003691MipsAsmParser::OperandMatchResultTy
3692MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003693 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003694 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00003695 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00003696 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00003697 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003698 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00003699 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00003700 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00003701
Jack Carterb5cf5902013-04-17 00:18:04 +00003702 if (getLexer().getKind() == AsmToken::LParen) {
3703 Parser.Lex();
3704 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003705 }
3706
Jack Carterb5cf5902013-04-17 00:18:04 +00003707 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003708 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00003709 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003710
Jack Carterd0bd6422013-04-18 00:41:53 +00003711 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003712 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003713 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003714 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00003715 SMLoc E =
3716 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003717 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00003718 return MatchOperand_Success;
3719 }
3720 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003721 SMLoc E =
3722 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00003723
Jack Carterd0bd6422013-04-18 00:41:53 +00003724 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00003725 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00003726 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00003727 S, E, *this);
3728 Operands.push_back(
3729 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00003730 return MatchOperand_Success;
3731 }
3732 Error(Parser.getTok().getLoc(), "'(' expected");
3733 return MatchOperand_ParseFail;
3734 }
3735
Jack Carterd0bd6422013-04-18 00:41:53 +00003736 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003737 }
3738
Toma Tabacu13964452014-09-04 13:23:44 +00003739 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003740 if (Res != MatchOperand_Success)
3741 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003742
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003743 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00003744 Error(Parser.getTok().getLoc(), "')' expected");
3745 return MatchOperand_ParseFail;
3746 }
3747
Jack Carter873c7242013-01-12 01:03:14 +00003748 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3749
Jack Carterd0bd6422013-04-18 00:41:53 +00003750 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003751
Craig Topper062a2ba2014-04-25 05:30:21 +00003752 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003753 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00003754
Jack Carterd0bd6422013-04-18 00:41:53 +00003755 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00003756 std::unique_ptr<MipsOperand> op(
3757 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00003758 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00003759 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003760 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00003761 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003762 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
3763 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00003764 if (IdVal->evaluateAsAbsolute(Imm))
3765 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003766 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003767 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00003768 getContext());
3769 }
3770
David Blaikie960ea3f2014-06-08 16:18:35 +00003771 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003772 return MatchOperand_Success;
3773}
3774
David Blaikie960ea3f2014-06-08 16:18:35 +00003775bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003776 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00003777 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00003778 if (Sym) {
3779 SMLoc S = Parser.getTok().getLoc();
3780 const MCExpr *Expr;
3781 if (Sym->isVariable())
3782 Expr = Sym->getVariableValue();
3783 else
3784 return false;
3785 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003786 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00003787 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00003788 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003789 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00003790 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00003791 if (ResTy == MatchOperand_Success) {
3792 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00003793 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00003794 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003795 llvm_unreachable("Should never ParseFail");
3796 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00003797 }
3798 } else if (Expr->getKind() == MCExpr::Constant) {
3799 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00003800 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00003801 Operands.push_back(
3802 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00003803 return true;
3804 }
3805 }
3806 return false;
3807}
Jack Carterd0bd6422013-04-18 00:41:53 +00003808
Jack Carter873c7242013-01-12 01:03:14 +00003809MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003810MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00003811 StringRef Identifier,
3812 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003813 int Index = matchCPURegisterName(Identifier);
3814 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003815 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003816 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3817 return MatchOperand_Success;
3818 }
3819
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003820 Index = matchHWRegsRegisterName(Identifier);
3821 if (Index != -1) {
3822 Operands.push_back(MipsOperand::createHWRegsReg(
3823 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3824 return MatchOperand_Success;
3825 }
3826
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003827 Index = matchFPURegisterName(Identifier);
3828 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003829 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003830 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3831 return MatchOperand_Success;
3832 }
3833
3834 Index = matchFCCRegisterName(Identifier);
3835 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003836 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003837 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3838 return MatchOperand_Success;
3839 }
3840
3841 Index = matchACRegisterName(Identifier);
3842 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003843 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003844 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3845 return MatchOperand_Success;
3846 }
3847
3848 Index = matchMSA128RegisterName(Identifier);
3849 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003850 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003851 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3852 return MatchOperand_Success;
3853 }
3854
3855 Index = matchMSA128CtrlRegisterName(Identifier);
3856 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003857 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003858 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3859 return MatchOperand_Success;
3860 }
3861
3862 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00003863}
3864
3865MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003866MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003867 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00003868 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003869
3870 if (Token.is(AsmToken::Identifier)) {
3871 DEBUG(dbgs() << ".. identifier\n");
3872 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00003873 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00003874 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00003875 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003876 } else if (Token.is(AsmToken::Integer)) {
3877 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00003878 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003879 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
3880 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003881 return MatchOperand_Success;
3882 }
3883
3884 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
3885
3886 return MatchOperand_NoMatch;
3887}
3888
David Blaikie960ea3f2014-06-08 16:18:35 +00003889MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003890MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003891 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00003892 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003893
3894 auto Token = Parser.getTok();
3895
3896 SMLoc S = Token.getLoc();
3897
3898 if (Token.isNot(AsmToken::Dollar)) {
3899 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
3900 if (Token.is(AsmToken::Identifier)) {
3901 if (searchSymbolAlias(Operands))
3902 return MatchOperand_Success;
3903 }
3904 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
3905 return MatchOperand_NoMatch;
3906 }
3907 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003908
Toma Tabacu13964452014-09-04 13:23:44 +00003909 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00003910 if (ResTy == MatchOperand_Success) {
3911 Parser.Lex(); // $
3912 Parser.Lex(); // identifier
3913 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003914 return ResTy;
3915}
3916
3917MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003918MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003919 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003920 switch (getLexer().getKind()) {
3921 default:
3922 return MatchOperand_NoMatch;
3923 case AsmToken::LParen:
3924 case AsmToken::Minus:
3925 case AsmToken::Plus:
3926 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00003927 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003928 case AsmToken::String:
3929 break;
3930 }
3931
3932 const MCExpr *IdVal;
3933 SMLoc S = Parser.getTok().getLoc();
3934 if (getParser().parseExpression(IdVal))
3935 return MatchOperand_ParseFail;
3936
3937 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3938 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
3939 return MatchOperand_Success;
3940}
3941
David Blaikie960ea3f2014-06-08 16:18:35 +00003942MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003943MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003944 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00003945 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003946
3947 SMLoc S = getLexer().getLoc();
3948
3949 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00003950 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003951 if (ResTy != MatchOperand_NoMatch)
3952 return ResTy;
3953
Daniel Sanders315386c2014-04-01 10:40:14 +00003954 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00003955 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00003956 if (ResTy != MatchOperand_NoMatch)
3957 return ResTy;
3958
Daniel Sandersffd84362014-04-01 10:41:48 +00003959 const MCExpr *Expr = nullptr;
3960 if (Parser.parseExpression(Expr)) {
3961 // We have no way of knowing if a symbol was consumed so we must ParseFail
3962 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003963 }
Daniel Sandersffd84362014-04-01 10:41:48 +00003964 Operands.push_back(
3965 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003966 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00003967}
3968
Vladimir Medic2b953d02013-10-01 09:48:56 +00003969MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00003970MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003971 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00003972 const MCExpr *IdVal;
3973 // If the first token is '$' we may have register operand.
3974 if (Parser.getTok().is(AsmToken::Dollar))
3975 return MatchOperand_NoMatch;
3976 SMLoc S = Parser.getTok().getLoc();
3977 if (getParser().parseExpression(IdVal))
3978 return MatchOperand_ParseFail;
3979 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00003980 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00003981 int64_t Val = MCE->getValue();
3982 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3983 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003984 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00003985 return MatchOperand_Success;
3986}
3987
Matheus Almeida779c5932013-11-18 12:32:49 +00003988MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003989MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003990 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00003991 switch (getLexer().getKind()) {
3992 default:
3993 return MatchOperand_NoMatch;
3994 case AsmToken::LParen:
3995 case AsmToken::Plus:
3996 case AsmToken::Minus:
3997 case AsmToken::Integer:
3998 break;
3999 }
4000
4001 const MCExpr *Expr;
4002 SMLoc S = Parser.getTok().getLoc();
4003
4004 if (getParser().parseExpression(Expr))
4005 return MatchOperand_ParseFail;
4006
4007 int64_t Val;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004008 if (!Expr->evaluateAsAbsolute(Val)) {
Matheus Almeida779c5932013-11-18 12:32:49 +00004009 Error(S, "expected immediate value");
4010 return MatchOperand_ParseFail;
4011 }
4012
4013 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
4014 // and because the CPU always adds one to the immediate field, the allowed
4015 // range becomes 1..4. We'll only check the range here and will deal
4016 // with the addition/subtraction when actually decoding/encoding
4017 // the instruction.
4018 if (Val < 1 || Val > 4) {
4019 Error(S, "immediate not in range (1..4)");
4020 return MatchOperand_ParseFail;
4021 }
4022
Jack Carter3b2c96e2014-01-22 23:31:38 +00004023 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004024 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00004025 return MatchOperand_Success;
4026}
4027
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004028MipsAsmParser::OperandMatchResultTy
4029MipsAsmParser::parseRegisterList(OperandVector &Operands) {
4030 MCAsmParser &Parser = getParser();
4031 SmallVector<unsigned, 10> Regs;
4032 unsigned RegNo;
4033 unsigned PrevReg = Mips::NoRegister;
4034 bool RegRange = false;
4035 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4036
4037 if (Parser.getTok().isNot(AsmToken::Dollar))
4038 return MatchOperand_ParseFail;
4039
4040 SMLoc S = Parser.getTok().getLoc();
4041 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
4042 SMLoc E = getLexer().getLoc();
4043 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
4044 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
4045 if (RegRange) {
4046 // Remove last register operand because registers from register range
4047 // should be inserted first.
4048 if (RegNo == Mips::RA) {
4049 Regs.push_back(RegNo);
4050 } else {
4051 unsigned TmpReg = PrevReg + 1;
4052 while (TmpReg <= RegNo) {
4053 if ((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) {
4054 Error(E, "invalid register operand");
4055 return MatchOperand_ParseFail;
4056 }
4057
4058 PrevReg = TmpReg;
4059 Regs.push_back(TmpReg++);
4060 }
4061 }
4062
4063 RegRange = false;
4064 } else {
4065 if ((PrevReg == Mips::NoRegister) && (RegNo != Mips::S0) &&
4066 (RegNo != Mips::RA)) {
4067 Error(E, "$16 or $31 expected");
4068 return MatchOperand_ParseFail;
4069 } else if (((RegNo < Mips::S0) || (RegNo > Mips::S7)) &&
4070 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
4071 Error(E, "invalid register operand");
4072 return MatchOperand_ParseFail;
4073 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
4074 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
4075 Error(E, "consecutive register numbers expected");
4076 return MatchOperand_ParseFail;
4077 }
4078
4079 Regs.push_back(RegNo);
4080 }
4081
4082 if (Parser.getTok().is(AsmToken::Minus))
4083 RegRange = true;
4084
4085 if (!Parser.getTok().isNot(AsmToken::Minus) &&
4086 !Parser.getTok().isNot(AsmToken::Comma)) {
4087 Error(E, "',' or '-' expected");
4088 return MatchOperand_ParseFail;
4089 }
4090
4091 Lex(); // Consume comma or minus
4092 if (Parser.getTok().isNot(AsmToken::Dollar))
4093 break;
4094
4095 PrevReg = RegNo;
4096 }
4097
4098 SMLoc E = Parser.getTok().getLoc();
4099 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4100 parseMemOperand(Operands);
4101 return MatchOperand_Success;
4102}
4103
Zoran Jovanovic2deca342014-12-16 14:59:10 +00004104MipsAsmParser::OperandMatchResultTy
4105MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
4106 MCAsmParser &Parser = getParser();
4107
4108 SMLoc S = Parser.getTok().getLoc();
4109 if (parseAnyRegister(Operands) != MatchOperand_Success)
4110 return MatchOperand_ParseFail;
4111
4112 SMLoc E = Parser.getTok().getLoc();
4113 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
4114 unsigned Reg = Op.getGPR32Reg();
4115 Operands.pop_back();
4116 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
4117 return MatchOperand_Success;
4118}
4119
Zoran Jovanovic41688672015-02-10 16:36:20 +00004120MipsAsmParser::OperandMatchResultTy
4121MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
4122 MCAsmParser &Parser = getParser();
4123 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4124 SmallVector<unsigned, 10> Regs;
4125
4126 if (Parser.getTok().isNot(AsmToken::Dollar))
4127 return MatchOperand_ParseFail;
4128
4129 SMLoc S = Parser.getTok().getLoc();
4130
4131 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4132 return MatchOperand_ParseFail;
4133
4134 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4135 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4136 Regs.push_back(RegNo);
4137
4138 SMLoc E = Parser.getTok().getLoc();
4139 if (Parser.getTok().isNot(AsmToken::Comma)) {
4140 Error(E, "',' expected");
4141 return MatchOperand_ParseFail;
4142 }
4143
4144 // Remove comma.
4145 Parser.Lex();
4146
4147 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4148 return MatchOperand_ParseFail;
4149
4150 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4151 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4152 Regs.push_back(RegNo);
4153
4154 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4155
4156 return MatchOperand_Success;
4157}
4158
Jack Carterdc1e35d2012-09-06 20:00:02 +00004159MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
4160
Vladimir Medic4c299852013-11-06 11:27:05 +00004161 MCSymbolRefExpr::VariantKind VK =
4162 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
4163 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
4164 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
4165 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
4166 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
4167 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
4168 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
4169 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
4170 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
4171 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
4172 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
4173 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
4174 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
4175 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
4176 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
4177 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
4178 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
4179 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00004180 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
4181 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
4182 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
4183 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
4184 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
4185 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00004186 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
4187 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00004188 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00004189
Matheus Almeida2852af82014-04-22 10:15:54 +00004190 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00004191
Jack Carterdc1e35d2012-09-06 20:00:02 +00004192 return VK;
4193}
Jack Cartera63b16a2012-09-07 00:23:42 +00004194
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004195/// Sometimes (i.e. load/stores) the operand may be followed immediately by
4196/// either this.
4197/// ::= '(', register, ')'
4198/// handle it before we iterate so we don't get tripped up by the lack of
4199/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004200bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004201 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004202 if (getLexer().is(AsmToken::LParen)) {
4203 Operands.push_back(
4204 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
4205 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004206 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004207 SMLoc Loc = getLexer().getLoc();
4208 Parser.eatToEndOfStatement();
4209 return Error(Loc, "unexpected token in argument list");
4210 }
4211 if (Parser.getTok().isNot(AsmToken::RParen)) {
4212 SMLoc Loc = getLexer().getLoc();
4213 Parser.eatToEndOfStatement();
4214 return Error(Loc, "unexpected token, expected ')'");
4215 }
4216 Operands.push_back(
4217 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
4218 Parser.Lex();
4219 }
4220 return false;
4221}
4222
4223/// Sometimes (i.e. in MSA) the operand may be followed immediately by
4224/// either one of these.
4225/// ::= '[', register, ']'
4226/// ::= '[', integer, ']'
4227/// handle it before we iterate so we don't get tripped up by the lack of
4228/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004229bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00004230 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004231 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004232 if (getLexer().is(AsmToken::LBrac)) {
4233 Operands.push_back(
4234 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
4235 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004236 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004237 SMLoc Loc = getLexer().getLoc();
4238 Parser.eatToEndOfStatement();
4239 return Error(Loc, "unexpected token in argument list");
4240 }
4241 if (Parser.getTok().isNot(AsmToken::RBrac)) {
4242 SMLoc Loc = getLexer().getLoc();
4243 Parser.eatToEndOfStatement();
4244 return Error(Loc, "unexpected token, expected ']'");
4245 }
4246 Operands.push_back(
4247 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
4248 Parser.Lex();
4249 }
4250 return false;
4251}
4252
David Blaikie960ea3f2014-06-08 16:18:35 +00004253bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
4254 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004255 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004256 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004257
4258 // We have reached first instruction, module directive are now forbidden.
4259 getTargetStreamer().forbidModuleDirective();
4260
Vladimir Medic74593e62013-07-17 15:00:42 +00004261 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00004262 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00004263 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00004264 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00004265 }
Vladimir Medic64828a12013-07-16 10:07:14 +00004266 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004267 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004268
4269 // Read the remaining operands.
4270 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4271 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004272 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004273 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004274 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004275 return Error(Loc, "unexpected token in argument list");
4276 }
Toma Tabacu13964452014-09-04 13:23:44 +00004277 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004278 return true;
4279 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00004280
Jack Carterd0bd6422013-04-18 00:41:53 +00004281 while (getLexer().is(AsmToken::Comma)) {
4282 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00004283 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004284 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004285 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004286 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004287 return Error(Loc, "unexpected token in argument list");
4288 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004289 // Parse bracket and parenthesis suffixes before we iterate
4290 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00004291 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004292 return true;
4293 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00004294 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004295 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00004296 }
4297 }
Jack Carterb4dbc172012-09-05 23:34:03 +00004298 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4299 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004300 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004301 return Error(Loc, "unexpected token in argument list");
4302 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004303 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00004304 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00004305}
4306
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004307bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004308 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004309 SMLoc Loc = getLexer().getLoc();
4310 Parser.eatToEndOfStatement();
4311 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00004312}
4313
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004314bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004315 return Error(Loc, ErrorMsg);
4316}
4317
Jack Carter0b744b32012-10-04 02:29:46 +00004318bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004319 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004320 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00004321
4322 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00004323 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00004324
4325 Parser.Lex(); // Eat "noat".
4326
Jack Carterd0bd6422013-04-18 00:41:53 +00004327 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004328 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004329 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004330 return false;
4331 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004332
4333 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004334 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004335 return false;
4336}
Jack Carterd0bd6422013-04-18 00:41:53 +00004337
Jack Carter0b744b32012-10-04 02:29:46 +00004338bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00004339 // Line can be: ".set at", which sets $at to $1
4340 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00004341 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00004342 Parser.Lex(); // Eat "at".
4343
Jack Carter0b744b32012-10-04 02:29:46 +00004344 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004345 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00004346 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00004347
4348 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004349 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004350 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00004351 }
4352
4353 if (getLexer().isNot(AsmToken::Equal)) {
4354 reportParseError("unexpected token, expected equals sign");
4355 return false;
4356 }
4357 Parser.Lex(); // Eat "=".
4358
4359 if (getLexer().isNot(AsmToken::Dollar)) {
4360 if (getLexer().is(AsmToken::EndOfStatement)) {
4361 reportParseError("no register specified");
4362 return false;
4363 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00004364 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00004365 return false;
4366 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004367 }
4368 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00004369
Toma Tabacu16a74492015-02-13 10:30:57 +00004370 // Find out what "reg" is.
4371 unsigned AtRegNo;
4372 const AsmToken &Reg = Parser.getTok();
4373 if (Reg.is(AsmToken::Identifier)) {
4374 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
4375 } else if (Reg.is(AsmToken::Integer)) {
4376 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00004377 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00004378 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00004379 return false;
4380 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004381
4382 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00004383 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004384 reportParseError("invalid register");
4385 return false;
4386 }
4387 Parser.Lex(); // Eat "reg".
4388
4389 // If this is not the end of the statement, report an error.
4390 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4391 reportParseError("unexpected token, expected end of statement");
4392 return false;
4393 }
4394
4395 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
4396
4397 Parser.Lex(); // Consume the EndOfStatement.
4398 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004399}
4400
4401bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004402 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004403 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004404 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004405 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004406 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004407 return false;
4408 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004409 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00004410 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004411 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004412 return false;
4413}
4414
4415bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004416 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004417 Parser.Lex();
4418 // If this is not the end of the statement, report an error.
4419 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004420 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004421 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00004422 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004423 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00004424 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004425 Parser.Lex(); // Consume the EndOfStatement.
4426 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004427}
4428
4429bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004430 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004431 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004432 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004433 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004434 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004435 return false;
4436 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004437 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00004438 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00004439 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004440 return false;
4441}
4442
4443bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004444 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004445 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004446 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004447 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004448 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004449 return false;
4450 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004451 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00004452 reportParseError("`noreorder' must be set before `nomacro'");
4453 return false;
4454 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004455 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00004456 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00004457 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004458 return false;
4459}
Jack Carterd76b2372013-03-21 21:44:16 +00004460
Daniel Sanders44934432014-08-07 12:03:36 +00004461bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004462 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00004463 Parser.Lex();
4464
4465 // If this is not the end of the statement, report an error.
4466 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004467 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00004468
4469 setFeatureBits(Mips::FeatureMSA, "msa");
4470 getTargetStreamer().emitDirectiveSetMsa();
4471 return false;
4472}
4473
4474bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004475 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00004476 Parser.Lex();
4477
4478 // If this is not the end of the statement, report an error.
4479 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004480 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00004481
4482 clearFeatureBits(Mips::FeatureMSA, "msa");
4483 getTargetStreamer().emitDirectiveSetNoMsa();
4484 return false;
4485}
4486
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004487bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004488 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004489 Parser.Lex(); // Eat "nodsp".
4490
4491 // If this is not the end of the statement, report an error.
4492 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4493 reportParseError("unexpected token, expected end of statement");
4494 return false;
4495 }
4496
4497 clearFeatureBits(Mips::FeatureDSP, "dsp");
4498 getTargetStreamer().emitDirectiveSetNoDsp();
4499 return false;
4500}
4501
Toma Tabacucc2502d2014-11-04 17:18:07 +00004502bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004503 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00004504 Parser.Lex(); // Eat "mips16".
4505
Jack Carter39536722014-01-22 23:08:42 +00004506 // If this is not the end of the statement, report an error.
4507 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004508 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00004509 return false;
4510 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00004511
4512 setFeatureBits(Mips::FeatureMips16, "mips16");
4513 getTargetStreamer().emitDirectiveSetMips16();
4514 Parser.Lex(); // Consume the EndOfStatement.
4515 return false;
4516}
4517
4518bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004519 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00004520 Parser.Lex(); // Eat "nomips16".
4521
4522 // If this is not the end of the statement, report an error.
4523 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4524 reportParseError("unexpected token, expected end of statement");
4525 return false;
4526 }
4527
4528 clearFeatureBits(Mips::FeatureMips16, "mips16");
4529 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00004530 Parser.Lex(); // Consume the EndOfStatement.
4531 return false;
4532}
4533
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004534bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004535 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004536 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004537 // Line can be: .set fp=32
4538 // .set fp=xx
4539 // .set fp=64
4540 Parser.Lex(); // Eat fp token
4541 AsmToken Tok = Parser.getTok();
4542 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004543 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004544 return false;
4545 }
4546 Parser.Lex(); // Eat '=' token.
4547 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004548
4549 if (!parseFpABIValue(FpAbiVal, ".set"))
4550 return false;
4551
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004552 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004553 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004554 return false;
4555 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004556 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004557 Parser.Lex(); // Consume the EndOfStatement.
4558 return false;
4559}
4560
Toma Tabacu32c72aa2015-06-30 09:36:50 +00004561bool MipsAsmParser::parseSetOddSPRegDirective() {
4562 MCAsmParser &Parser = getParser();
4563
4564 Parser.Lex(); // Eat "oddspreg".
4565 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4566 reportParseError("unexpected token, expected end of statement");
4567 return false;
4568 }
4569
4570 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4571 getTargetStreamer().emitDirectiveSetOddSPReg();
4572 return false;
4573}
4574
4575bool MipsAsmParser::parseSetNoOddSPRegDirective() {
4576 MCAsmParser &Parser = getParser();
4577
4578 Parser.Lex(); // Eat "nooddspreg".
4579 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4580 reportParseError("unexpected token, expected end of statement");
4581 return false;
4582 }
4583
4584 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4585 getTargetStreamer().emitDirectiveSetNoOddSPReg();
4586 return false;
4587}
4588
Toma Tabacu9db22db2014-09-09 10:15:38 +00004589bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004590 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00004591 SMLoc Loc = getLexer().getLoc();
4592
4593 Parser.Lex();
4594 if (getLexer().isNot(AsmToken::EndOfStatement))
4595 return reportParseError("unexpected token, expected end of statement");
4596
4597 // Always keep an element on the options "stack" to prevent the user
4598 // from changing the initial options. This is how we remember them.
4599 if (AssemblerOptions.size() == 2)
4600 return reportParseError(Loc, ".set pop with no .set push");
4601
4602 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00004603 setAvailableFeatures(
4604 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
4605 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00004606
4607 getTargetStreamer().emitDirectiveSetPop();
4608 return false;
4609}
4610
4611bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004612 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00004613 Parser.Lex();
4614 if (getLexer().isNot(AsmToken::EndOfStatement))
4615 return reportParseError("unexpected token, expected end of statement");
4616
4617 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00004618 AssemblerOptions.push_back(
4619 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00004620
4621 getTargetStreamer().emitDirectiveSetPush();
4622 return false;
4623}
4624
Toma Tabacu29696502015-06-02 09:48:04 +00004625bool MipsAsmParser::parseSetSoftFloatDirective() {
4626 MCAsmParser &Parser = getParser();
4627 Parser.Lex();
4628 if (getLexer().isNot(AsmToken::EndOfStatement))
4629 return reportParseError("unexpected token, expected end of statement");
4630
4631 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
4632 getTargetStreamer().emitDirectiveSetSoftFloat();
4633 return false;
4634}
4635
4636bool MipsAsmParser::parseSetHardFloatDirective() {
4637 MCAsmParser &Parser = getParser();
4638 Parser.Lex();
4639 if (getLexer().isNot(AsmToken::EndOfStatement))
4640 return reportParseError("unexpected token, expected end of statement");
4641
4642 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
4643 getTargetStreamer().emitDirectiveSetHardFloat();
4644 return false;
4645}
4646
Jack Carterd76b2372013-03-21 21:44:16 +00004647bool MipsAsmParser::parseSetAssignment() {
4648 StringRef Name;
4649 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00004650 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00004651
4652 if (Parser.parseIdentifier(Name))
4653 reportParseError("expected identifier after .set");
4654
4655 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00004656 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00004657 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00004658
Jack Carter3b2c96e2014-01-22 23:31:38 +00004659 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00004660 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00004661
Jim Grosbach6f482002015-05-18 18:43:14 +00004662 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00004663 Sym->setVariableValue(Value);
4664
4665 return false;
4666}
Jack Carterd0bd6422013-04-18 00:41:53 +00004667
Toma Tabacu26647792014-09-09 12:52:14 +00004668bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004669 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00004670 Parser.Lex();
4671 if (getLexer().isNot(AsmToken::EndOfStatement))
4672 return reportParseError("unexpected token, expected end of statement");
4673
4674 // Reset assembler options to their initial values.
Toma Tabacu465acfd2015-06-09 13:33:26 +00004675 setAvailableFeatures(
4676 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
4677 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00004678 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
4679
4680 getTargetStreamer().emitDirectiveSetMips0();
4681 return false;
4682}
4683
Toma Tabacu85618b32014-08-19 14:22:52 +00004684bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004685 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00004686 Parser.Lex();
4687 if (getLexer().isNot(AsmToken::Equal))
4688 return reportParseError("unexpected token, expected equals sign");
4689
4690 Parser.Lex();
4691 StringRef Arch;
4692 if (Parser.parseIdentifier(Arch))
4693 return reportParseError("expected arch identifier");
4694
4695 StringRef ArchFeatureName =
4696 StringSwitch<StringRef>(Arch)
4697 .Case("mips1", "mips1")
4698 .Case("mips2", "mips2")
4699 .Case("mips3", "mips3")
4700 .Case("mips4", "mips4")
4701 .Case("mips5", "mips5")
4702 .Case("mips32", "mips32")
4703 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00004704 .Case("mips32r3", "mips32r3")
4705 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00004706 .Case("mips32r6", "mips32r6")
4707 .Case("mips64", "mips64")
4708 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00004709 .Case("mips64r3", "mips64r3")
4710 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00004711 .Case("mips64r6", "mips64r6")
4712 .Case("cnmips", "cnmips")
4713 .Case("r4000", "mips3") // This is an implementation of Mips3.
4714 .Default("");
4715
4716 if (ArchFeatureName.empty())
4717 return reportParseError("unsupported architecture");
4718
4719 selectArch(ArchFeatureName);
4720 getTargetStreamer().emitDirectiveSetArch(Arch);
4721 return false;
4722}
4723
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004724bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004725 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004726 Parser.Lex();
4727 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004728 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004729
Matheus Almeida2852af82014-04-22 10:15:54 +00004730 switch (Feature) {
4731 default:
4732 llvm_unreachable("Unimplemented feature");
4733 case Mips::FeatureDSP:
4734 setFeatureBits(Mips::FeatureDSP, "dsp");
4735 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004736 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004737 case Mips::FeatureMicroMips:
4738 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004739 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004740 case Mips::FeatureMips1:
4741 selectArch("mips1");
4742 getTargetStreamer().emitDirectiveSetMips1();
4743 break;
4744 case Mips::FeatureMips2:
4745 selectArch("mips2");
4746 getTargetStreamer().emitDirectiveSetMips2();
4747 break;
4748 case Mips::FeatureMips3:
4749 selectArch("mips3");
4750 getTargetStreamer().emitDirectiveSetMips3();
4751 break;
4752 case Mips::FeatureMips4:
4753 selectArch("mips4");
4754 getTargetStreamer().emitDirectiveSetMips4();
4755 break;
4756 case Mips::FeatureMips5:
4757 selectArch("mips5");
4758 getTargetStreamer().emitDirectiveSetMips5();
4759 break;
4760 case Mips::FeatureMips32:
4761 selectArch("mips32");
4762 getTargetStreamer().emitDirectiveSetMips32();
4763 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004764 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004765 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00004766 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004767 break;
Daniel Sanders17793142015-02-18 16:24:50 +00004768 case Mips::FeatureMips32r3:
4769 selectArch("mips32r3");
4770 getTargetStreamer().emitDirectiveSetMips32R3();
4771 break;
4772 case Mips::FeatureMips32r5:
4773 selectArch("mips32r5");
4774 getTargetStreamer().emitDirectiveSetMips32R5();
4775 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004776 case Mips::FeatureMips32r6:
4777 selectArch("mips32r6");
4778 getTargetStreamer().emitDirectiveSetMips32R6();
4779 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004780 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004781 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00004782 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00004783 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004784 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004785 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00004786 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00004787 break;
Daniel Sanders17793142015-02-18 16:24:50 +00004788 case Mips::FeatureMips64r3:
4789 selectArch("mips64r3");
4790 getTargetStreamer().emitDirectiveSetMips64R3();
4791 break;
4792 case Mips::FeatureMips64r5:
4793 selectArch("mips64r5");
4794 getTargetStreamer().emitDirectiveSetMips64R5();
4795 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004796 case Mips::FeatureMips64r6:
4797 selectArch("mips64r6");
4798 getTargetStreamer().emitDirectiveSetMips64R6();
4799 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004800 }
4801 return false;
4802}
4803
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004804bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004805 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004806 if (getLexer().isNot(AsmToken::Comma)) {
4807 SMLoc Loc = getLexer().getLoc();
4808 Parser.eatToEndOfStatement();
4809 return Error(Loc, ErrorStr);
4810 }
4811
Matheus Almeida2852af82014-04-22 10:15:54 +00004812 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004813 return true;
4814}
4815
Daniel Sanderse2982ad2015-09-17 16:08:39 +00004816// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
4817// In this class, it is only used for .cprestore.
4818// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
4819// MipsTargetELFStreamer and MipsAsmParser.
4820bool MipsAsmParser::isPicAndNotNxxAbi() {
4821 return inPicMode() && !(isABI_N32() || isABI_N64());
4822}
4823
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004824bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00004825 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00004826 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004827
Toma Tabacudde4c462014-11-06 10:02:45 +00004828 if (inMips16Mode()) {
4829 reportParseError(".cpload is not supported in Mips16 mode");
4830 return false;
4831 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004832
David Blaikie960ea3f2014-06-08 16:18:35 +00004833 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00004834 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004835 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4836 reportParseError("expected register containing function address");
4837 return false;
4838 }
4839
David Blaikie960ea3f2014-06-08 16:18:35 +00004840 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
4841 if (!RegOpnd.isGPRAsmReg()) {
4842 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004843 return false;
4844 }
4845
Toma Tabacudde4c462014-11-06 10:02:45 +00004846 // If this is not the end of the statement, report an error.
4847 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4848 reportParseError("unexpected token, expected end of statement");
4849 return false;
4850 }
4851
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004852 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004853 return false;
4854}
4855
Daniel Sanderse2982ad2015-09-17 16:08:39 +00004856bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
4857 MCAsmParser &Parser = getParser();
4858
4859 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
4860 // is used in non-PIC mode.
4861
4862 if (inMips16Mode()) {
4863 reportParseError(".cprestore is not supported in Mips16 mode");
4864 return false;
4865 }
4866
4867 // Get the stack offset value.
4868 const MCExpr *StackOffset;
4869 int64_t StackOffsetVal;
4870 if (Parser.parseExpression(StackOffset)) {
4871 reportParseError("expected stack offset value");
4872 return false;
4873 }
4874
4875 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
4876 reportParseError("stack offset is not an absolute expression");
4877 return false;
4878 }
4879
4880 if (StackOffsetVal < 0) {
4881 Warning(Loc, ".cprestore with negative stack offset has no effect");
4882 IsCpRestoreSet = false;
4883 } else {
4884 IsCpRestoreSet = true;
4885 CpRestoreOffset = StackOffsetVal;
4886 }
4887
4888 // If this is not the end of the statement, report an error.
4889 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4890 reportParseError("unexpected token, expected end of statement");
4891 return false;
4892 }
4893
4894 // Store the $gp on the stack.
4895 SmallVector<MCInst, 3> StoreInsts;
4896 createCpRestoreMemOp(false /*IsLoad*/, CpRestoreOffset /*StackOffset*/, Loc,
4897 StoreInsts);
4898
4899 getTargetStreamer().emitDirectiveCpRestore(StoreInsts, CpRestoreOffset);
4900 Parser.Lex(); // Consume the EndOfStatement.
4901 return false;
4902}
4903
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004904bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004905 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004906 unsigned FuncReg;
4907 unsigned Save;
4908 bool SaveIsReg = true;
4909
Matheus Almeida7e815762014-06-18 13:08:59 +00004910 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00004911 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00004912 if (ResTy == MatchOperand_NoMatch) {
4913 reportParseError("expected register containing function address");
4914 Parser.eatToEndOfStatement();
4915 return false;
4916 }
4917
4918 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4919 if (!FuncRegOpnd.isGPRAsmReg()) {
4920 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
4921 Parser.eatToEndOfStatement();
4922 return false;
4923 }
4924
4925 FuncReg = FuncRegOpnd.getGPR32Reg();
4926 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004927
Toma Tabacu65f10572014-09-16 15:00:52 +00004928 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004929 return true;
4930
Toma Tabacu13964452014-09-04 13:23:44 +00004931 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00004932 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00004933 const MCExpr *OffsetExpr;
4934 int64_t OffsetVal;
4935 SMLoc ExprLoc = getLexer().getLoc();
4936
4937 if (Parser.parseExpression(OffsetExpr) ||
4938 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
4939 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00004940 Parser.eatToEndOfStatement();
4941 return false;
4942 }
Daniel Sanders5d796282015-09-21 09:26:55 +00004943
4944 Save = OffsetVal;
4945 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00004946 } else {
4947 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4948 if (!SaveOpnd.isGPRAsmReg()) {
4949 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
4950 Parser.eatToEndOfStatement();
4951 return false;
4952 }
4953 Save = SaveOpnd.getGPR32Reg();
4954 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004955
Toma Tabacu65f10572014-09-16 15:00:52 +00004956 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004957 return true;
4958
Toma Tabacu8874eac2015-02-18 13:46:53 +00004959 const MCExpr *Expr;
4960 if (Parser.parseExpression(Expr)) {
4961 reportParseError("expected expression");
4962 return false;
4963 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004964
Toma Tabacu8874eac2015-02-18 13:46:53 +00004965 if (Expr->getKind() != MCExpr::SymbolRef) {
4966 reportParseError("expected symbol");
4967 return false;
4968 }
4969 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
4970
Daniel Sandersf173dda2015-09-22 10:50:09 +00004971 CpSaveLocation = Save;
4972 CpSaveLocationIsRegister = SaveIsReg;
4973
Toma Tabacu8874eac2015-02-18 13:46:53 +00004974 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
4975 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004976 return false;
4977}
4978
Daniel Sandersf173dda2015-09-22 10:50:09 +00004979bool MipsAsmParser::parseDirectiveCPReturn() {
4980 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
4981 CpSaveLocationIsRegister);
4982 return false;
4983}
4984
Matheus Almeida0051f2d2014-04-16 15:48:55 +00004985bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004986 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00004987 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4988 const AsmToken &Tok = Parser.getTok();
4989
4990 if (Tok.getString() == "2008") {
4991 Parser.Lex();
4992 getTargetStreamer().emitDirectiveNaN2008();
4993 return false;
4994 } else if (Tok.getString() == "legacy") {
4995 Parser.Lex();
4996 getTargetStreamer().emitDirectiveNaNLegacy();
4997 return false;
4998 }
4999 }
5000 // If we don't recognize the option passed to the .nan
5001 // directive (e.g. no option or unknown option), emit an error.
5002 reportParseError("invalid option in .nan directive");
5003 return false;
5004}
5005
Jack Carter0b744b32012-10-04 02:29:46 +00005006bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005007 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005008 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00005009 const AsmToken &Tok = Parser.getTok();
5010
5011 if (Tok.getString() == "noat") {
5012 return parseSetNoAtDirective();
5013 } else if (Tok.getString() == "at") {
5014 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00005015 } else if (Tok.getString() == "arch") {
5016 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005017 } else if (Tok.getString() == "fp") {
5018 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005019 } else if (Tok.getString() == "oddspreg") {
5020 return parseSetOddSPRegDirective();
5021 } else if (Tok.getString() == "nooddspreg") {
5022 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005023 } else if (Tok.getString() == "pop") {
5024 return parseSetPopDirective();
5025 } else if (Tok.getString() == "push") {
5026 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00005027 } else if (Tok.getString() == "reorder") {
5028 return parseSetReorderDirective();
5029 } else if (Tok.getString() == "noreorder") {
5030 return parseSetNoReorderDirective();
5031 } else if (Tok.getString() == "macro") {
5032 return parseSetMacroDirective();
5033 } else if (Tok.getString() == "nomacro") {
5034 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00005035 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00005036 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005037 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00005038 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005039 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00005040 getTargetStreamer().emitDirectiveSetNoMicroMips();
5041 Parser.eatToEndOfStatement();
5042 return false;
5043 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005044 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00005045 } else if (Tok.getString() == "mips0") {
5046 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00005047 } else if (Tok.getString() == "mips1") {
5048 return parseSetFeature(Mips::FeatureMips1);
5049 } else if (Tok.getString() == "mips2") {
5050 return parseSetFeature(Mips::FeatureMips2);
5051 } else if (Tok.getString() == "mips3") {
5052 return parseSetFeature(Mips::FeatureMips3);
5053 } else if (Tok.getString() == "mips4") {
5054 return parseSetFeature(Mips::FeatureMips4);
5055 } else if (Tok.getString() == "mips5") {
5056 return parseSetFeature(Mips::FeatureMips5);
5057 } else if (Tok.getString() == "mips32") {
5058 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00005059 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005060 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005061 } else if (Tok.getString() == "mips32r3") {
5062 return parseSetFeature(Mips::FeatureMips32r3);
5063 } else if (Tok.getString() == "mips32r5") {
5064 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005065 } else if (Tok.getString() == "mips32r6") {
5066 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005067 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005068 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005069 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005070 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005071 } else if (Tok.getString() == "mips64r3") {
5072 return parseSetFeature(Mips::FeatureMips64r3);
5073 } else if (Tok.getString() == "mips64r5") {
5074 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005075 } else if (Tok.getString() == "mips64r6") {
5076 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00005077 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005078 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005079 } else if (Tok.getString() == "nodsp") {
5080 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00005081 } else if (Tok.getString() == "msa") {
5082 return parseSetMsaDirective();
5083 } else if (Tok.getString() == "nomsa") {
5084 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00005085 } else if (Tok.getString() == "softfloat") {
5086 return parseSetSoftFloatDirective();
5087 } else if (Tok.getString() == "hardfloat") {
5088 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00005089 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00005090 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00005091 parseSetAssignment();
5092 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005093 }
Jack Carter07c818d2013-01-25 01:31:34 +00005094
Jack Carter0b744b32012-10-04 02:29:46 +00005095 return true;
5096}
5097
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005098/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00005099/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005100bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005101 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005102 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5103 for (;;) {
5104 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005105 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00005106 return true;
5107
5108 getParser().getStreamer().EmitValue(Value, Size);
5109
5110 if (getLexer().is(AsmToken::EndOfStatement))
5111 break;
5112
Jack Carter07c818d2013-01-25 01:31:34 +00005113 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005114 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00005115 Parser.Lex();
5116 }
5117 }
5118
5119 Parser.Lex();
5120 return false;
5121}
5122
Vladimir Medic4c299852013-11-06 11:27:05 +00005123/// parseDirectiveGpWord
5124/// ::= .gpword local_sym
5125bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005126 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00005127 const MCExpr *Value;
5128 // EmitGPRel32Value requires an expression, so we are using base class
5129 // method to evaluate the expression.
5130 if (getParser().parseExpression(Value))
5131 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00005132 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00005133
Vladimir Medice10c1122013-11-13 13:18:04 +00005134 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005135 return Error(getLexer().getLoc(),
5136 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00005137 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00005138 return false;
5139}
5140
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005141/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00005142/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005143bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005144 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005145 const MCExpr *Value;
5146 // EmitGPRel64Value requires an expression, so we are using base class
5147 // method to evaluate the expression.
5148 if (getParser().parseExpression(Value))
5149 return true;
5150 getParser().getStreamer().EmitGPRel64Value(Value);
5151
5152 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005153 return Error(getLexer().getLoc(),
5154 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00005155 Parser.Lex(); // Eat EndOfStatement token.
5156 return false;
5157}
5158
Jack Carter0cd3c192014-01-06 23:27:31 +00005159bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005160 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00005161 // Get the option token.
5162 AsmToken Tok = Parser.getTok();
5163 // At the moment only identifiers are supported.
5164 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005165 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00005166 Parser.eatToEndOfStatement();
5167 return false;
5168 }
5169
5170 StringRef Option = Tok.getIdentifier();
5171
5172 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005173 // MipsAsmParser needs to know if the current PIC mode changes.
5174 IsPicEnabled = false;
5175
Jack Carter0cd3c192014-01-06 23:27:31 +00005176 getTargetStreamer().emitDirectiveOptionPic0();
5177 Parser.Lex();
5178 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5179 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005180 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005181 Parser.eatToEndOfStatement();
5182 }
5183 return false;
5184 }
5185
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005186 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005187 // MipsAsmParser needs to know if the current PIC mode changes.
5188 IsPicEnabled = true;
5189
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005190 getTargetStreamer().emitDirectiveOptionPic2();
5191 Parser.Lex();
5192 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5193 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005194 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005195 Parser.eatToEndOfStatement();
5196 }
5197 return false;
5198 }
5199
Jack Carter0cd3c192014-01-06 23:27:31 +00005200 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00005201 Warning(Parser.getTok().getLoc(),
5202 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00005203 Parser.eatToEndOfStatement();
5204 return false;
5205}
5206
Toma Tabacu9ca50962015-04-16 09:53:47 +00005207/// parseInsnDirective
5208/// ::= .insn
5209bool MipsAsmParser::parseInsnDirective() {
5210 // If this is not the end of the statement, report an error.
5211 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5212 reportParseError("unexpected token, expected end of statement");
5213 return false;
5214 }
5215
5216 // The actual label marking happens in
5217 // MipsELFStreamer::createPendingLabelRelocs().
5218 getTargetStreamer().emitDirectiveInsn();
5219
5220 getParser().Lex(); // Eat EndOfStatement token.
5221 return false;
5222}
5223
Daniel Sanders7e527422014-07-10 13:38:23 +00005224/// parseDirectiveModule
5225/// ::= .module oddspreg
5226/// ::= .module nooddspreg
5227/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00005228/// ::= .module softfloat
5229/// ::= .module hardfloat
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005230bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005231 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005232 MCAsmLexer &Lexer = getLexer();
5233 SMLoc L = Lexer.getLoc();
5234
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00005235 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005236 // TODO : get a better message.
5237 reportParseError(".module directive must appear before any code");
5238 return false;
5239 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005240
Toma Tabacuc405c822015-01-23 10:40:19 +00005241 StringRef Option;
5242 if (Parser.parseIdentifier(Option)) {
5243 reportParseError("expected .module option identifier");
5244 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005245 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005246
Toma Tabacuc405c822015-01-23 10:40:19 +00005247 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005248 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005249
Toma Tabacu3c499582015-06-25 10:56:57 +00005250 // Synchronize the abiflags information with the FeatureBits information we
5251 // changed above.
5252 getTargetStreamer().updateABIInfo(*this);
5253
5254 // If printing assembly, use the recently updated abiflags information.
5255 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5256 // emitted at the end).
5257 getTargetStreamer().emitDirectiveModuleOddSPReg();
5258
Toma Tabacuc405c822015-01-23 10:40:19 +00005259 // If this is not the end of the statement, report an error.
5260 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5261 reportParseError("unexpected token, expected end of statement");
5262 return false;
5263 }
5264
5265 return false; // parseDirectiveModule has finished successfully.
5266 } else if (Option == "nooddspreg") {
5267 if (!isABI_O32()) {
5268 Error(L, "'.module nooddspreg' requires the O32 ABI");
5269 return false;
5270 }
5271
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005272 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005273
Toma Tabacu3c499582015-06-25 10:56:57 +00005274 // Synchronize the abiflags information with the FeatureBits information we
5275 // changed above.
5276 getTargetStreamer().updateABIInfo(*this);
5277
5278 // If printing assembly, use the recently updated abiflags information.
5279 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5280 // emitted at the end).
5281 getTargetStreamer().emitDirectiveModuleOddSPReg();
5282
Toma Tabacuc405c822015-01-23 10:40:19 +00005283 // If this is not the end of the statement, report an error.
5284 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5285 reportParseError("unexpected token, expected end of statement");
5286 return false;
5287 }
5288
5289 return false; // parseDirectiveModule has finished successfully.
5290 } else if (Option == "fp") {
5291 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00005292 } else if (Option == "softfloat") {
5293 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5294
5295 // Synchronize the ABI Flags information with the FeatureBits information we
5296 // updated above.
5297 getTargetStreamer().updateABIInfo(*this);
5298
5299 // If printing assembly, use the recently updated ABI Flags information.
5300 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5301 // emitted later).
5302 getTargetStreamer().emitDirectiveModuleSoftFloat();
5303
5304 // If this is not the end of the statement, report an error.
5305 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5306 reportParseError("unexpected token, expected end of statement");
5307 return false;
5308 }
5309
5310 return false; // parseDirectiveModule has finished successfully.
5311 } else if (Option == "hardfloat") {
5312 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5313
5314 // Synchronize the ABI Flags information with the FeatureBits information we
5315 // updated above.
5316 getTargetStreamer().updateABIInfo(*this);
5317
5318 // If printing assembly, use the recently updated ABI Flags information.
5319 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5320 // emitted later).
5321 getTargetStreamer().emitDirectiveModuleHardFloat();
5322
5323 // If this is not the end of the statement, report an error.
5324 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5325 reportParseError("unexpected token, expected end of statement");
5326 return false;
5327 }
5328
5329 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00005330 } else {
5331 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
5332 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005333}
5334
5335/// parseDirectiveModuleFP
5336/// ::= =32
5337/// ::= =xx
5338/// ::= =64
5339bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005340 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005341 MCAsmLexer &Lexer = getLexer();
5342
5343 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005344 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005345 return false;
5346 }
5347 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005348
Daniel Sanders7e527422014-07-10 13:38:23 +00005349 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005350 if (!parseFpABIValue(FpABI, ".module"))
5351 return false;
5352
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005353 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005354 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005355 return false;
5356 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005357
Toma Tabacua64e5402015-06-25 12:44:38 +00005358 // Synchronize the abiflags information with the FeatureBits information we
5359 // changed above.
5360 getTargetStreamer().updateABIInfo(*this);
5361
5362 // If printing assembly, use the recently updated abiflags information.
5363 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5364 // emitted at the end).
5365 getTargetStreamer().emitDirectiveModuleFP();
5366
Daniel Sanders7e527422014-07-10 13:38:23 +00005367 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005368 return false;
5369}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005370
Daniel Sanders7e527422014-07-10 13:38:23 +00005371bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005372 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005373 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005374 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005375 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005376
5377 if (Lexer.is(AsmToken::Identifier)) {
5378 StringRef Value = Parser.getTok().getString();
5379 Parser.Lex();
5380
5381 if (Value != "xx") {
5382 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5383 return false;
5384 }
5385
5386 if (!isABI_O32()) {
5387 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
5388 return false;
5389 }
5390
Daniel Sanders7e527422014-07-10 13:38:23 +00005391 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005392 if (ModuleLevelOptions) {
5393 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5394 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5395 } else {
5396 setFeatureBits(Mips::FeatureFPXX, "fpxx");
5397 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5398 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005399 return true;
5400 }
5401
5402 if (Lexer.is(AsmToken::Integer)) {
5403 unsigned Value = Parser.getTok().getIntVal();
5404 Parser.Lex();
5405
5406 if (Value != 32 && Value != 64) {
5407 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5408 return false;
5409 }
5410
5411 if (Value == 32) {
5412 if (!isABI_O32()) {
5413 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
5414 return false;
5415 }
5416
Daniel Sanders7e527422014-07-10 13:38:23 +00005417 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005418 if (ModuleLevelOptions) {
5419 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5420 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5421 } else {
5422 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
5423 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5424 }
Toma Tabacua64e5402015-06-25 12:44:38 +00005425 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00005426 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005427 if (ModuleLevelOptions) {
5428 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5429 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5430 } else {
5431 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
5432 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
5433 }
Toma Tabacua64e5402015-06-25 12:44:38 +00005434 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005435
Daniel Sanders7e527422014-07-10 13:38:23 +00005436 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005437 }
5438
5439 return false;
5440}
5441
Jack Carter0b744b32012-10-04 02:29:46 +00005442bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005443 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005444 StringRef IDVal = DirectiveID.getString();
5445
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005446 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005447 return parseDirectiveCpLoad(DirectiveID.getLoc());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005448 if (IDVal == ".cprestore")
5449 return parseDirectiveCpRestore(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00005450 if (IDVal == ".dword") {
5451 parseDataDirective(8, DirectiveID.getLoc());
5452 return false;
5453 }
Jack Carterd0bd6422013-04-18 00:41:53 +00005454 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005455 StringRef SymbolName;
5456
5457 if (Parser.parseIdentifier(SymbolName)) {
5458 reportParseError("expected identifier after .ent");
5459 return false;
5460 }
5461
5462 // There's an undocumented extension that allows an integer to
5463 // follow the name of the procedure which AFAICS is ignored by GAS.
5464 // Example: .ent foo,2
5465 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5466 if (getLexer().isNot(AsmToken::Comma)) {
5467 // Even though we accept this undocumented extension for compatibility
5468 // reasons, the additional integer argument does not actually change
5469 // the behaviour of the '.ent' directive, so we would like to discourage
5470 // its use. We do this by not referring to the extended version in
5471 // error messages which are not directly related to its use.
5472 reportParseError("unexpected token, expected end of statement");
5473 return false;
5474 }
5475 Parser.Lex(); // Eat the comma.
5476 const MCExpr *DummyNumber;
5477 int64_t DummyNumberVal;
5478 // If the user was explicitly trying to use the extended version,
5479 // we still give helpful extension-related error messages.
5480 if (Parser.parseExpression(DummyNumber)) {
5481 reportParseError("expected number after comma");
5482 return false;
5483 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00005484 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005485 reportParseError("expected an absolute expression after comma");
5486 return false;
5487 }
5488 }
5489
5490 // If this is not the end of the statement, report an error.
5491 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5492 reportParseError("unexpected token, expected end of statement");
5493 return false;
5494 }
5495
Jim Grosbach6f482002015-05-18 18:43:14 +00005496 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005497
5498 getTargetStreamer().emitDirectiveEnt(*Sym);
5499 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005500 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00005501 return false;
5502 }
5503
Jack Carter07c818d2013-01-25 01:31:34 +00005504 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005505 StringRef SymbolName;
5506
5507 if (Parser.parseIdentifier(SymbolName)) {
5508 reportParseError("expected identifier after .end");
5509 return false;
5510 }
5511
5512 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5513 reportParseError("unexpected token, expected end of statement");
5514 return false;
5515 }
5516
5517 if (CurrentFn == nullptr) {
5518 reportParseError(".end used without .ent");
5519 return false;
5520 }
5521
5522 if ((SymbolName != CurrentFn->getName())) {
5523 reportParseError(".end symbol does not match .ent symbol");
5524 return false;
5525 }
5526
5527 getTargetStreamer().emitDirectiveEnd(SymbolName);
5528 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005529 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00005530 return false;
5531 }
5532
Jack Carter07c818d2013-01-25 01:31:34 +00005533 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005534 // .frame $stack_reg, frame_size_in_bytes, $return_reg
5535 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005536 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005537 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5538 reportParseError("expected stack register");
5539 return false;
5540 }
5541
5542 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5543 if (!StackRegOpnd.isGPRAsmReg()) {
5544 reportParseError(StackRegOpnd.getStartLoc(),
5545 "expected general purpose register");
5546 return false;
5547 }
5548 unsigned StackReg = StackRegOpnd.getGPR32Reg();
5549
5550 if (Parser.getTok().is(AsmToken::Comma))
5551 Parser.Lex();
5552 else {
5553 reportParseError("unexpected token, expected comma");
5554 return false;
5555 }
5556
5557 // Parse the frame size.
5558 const MCExpr *FrameSize;
5559 int64_t FrameSizeVal;
5560
5561 if (Parser.parseExpression(FrameSize)) {
5562 reportParseError("expected frame size value");
5563 return false;
5564 }
5565
Jim Grosbach13760bd2015-05-30 01:25:56 +00005566 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005567 reportParseError("frame size not an absolute expression");
5568 return false;
5569 }
5570
5571 if (Parser.getTok().is(AsmToken::Comma))
5572 Parser.Lex();
5573 else {
5574 reportParseError("unexpected token, expected comma");
5575 return false;
5576 }
5577
5578 // Parse the return register.
5579 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00005580 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005581 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5582 reportParseError("expected return register");
5583 return false;
5584 }
5585
5586 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5587 if (!ReturnRegOpnd.isGPRAsmReg()) {
5588 reportParseError(ReturnRegOpnd.getStartLoc(),
5589 "expected general purpose register");
5590 return false;
5591 }
5592
5593 // If this is not the end of the statement, report an error.
5594 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5595 reportParseError("unexpected token, expected end of statement");
5596 return false;
5597 }
5598
5599 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
5600 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005601 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00005602 return false;
5603 }
5604
Jack Carter07c818d2013-01-25 01:31:34 +00005605 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00005606 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00005607 }
5608
Daniel Sandersd97a6342014-08-13 10:07:34 +00005609 if (IDVal == ".mask" || IDVal == ".fmask") {
5610 // .mask bitmask, frame_offset
5611 // bitmask: One bit for each register used.
5612 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
5613 // first register is expected to be saved.
5614 // Examples:
5615 // .mask 0x80000000, -4
5616 // .fmask 0x80000000, -4
5617 //
Jack Carterbe332172012-09-07 00:48:02 +00005618
Daniel Sandersd97a6342014-08-13 10:07:34 +00005619 // Parse the bitmask
5620 const MCExpr *BitMask;
5621 int64_t BitMaskVal;
5622
5623 if (Parser.parseExpression(BitMask)) {
5624 reportParseError("expected bitmask value");
5625 return false;
5626 }
5627
Jim Grosbach13760bd2015-05-30 01:25:56 +00005628 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005629 reportParseError("bitmask not an absolute expression");
5630 return false;
5631 }
5632
5633 if (Parser.getTok().is(AsmToken::Comma))
5634 Parser.Lex();
5635 else {
5636 reportParseError("unexpected token, expected comma");
5637 return false;
5638 }
5639
5640 // Parse the frame_offset
5641 const MCExpr *FrameOffset;
5642 int64_t FrameOffsetVal;
5643
5644 if (Parser.parseExpression(FrameOffset)) {
5645 reportParseError("expected frame offset value");
5646 return false;
5647 }
5648
Jim Grosbach13760bd2015-05-30 01:25:56 +00005649 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005650 reportParseError("frame offset not an absolute expression");
5651 return false;
5652 }
5653
5654 // If this is not the end of the statement, report an error.
5655 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5656 reportParseError("unexpected token, expected end of statement");
5657 return false;
5658 }
5659
5660 if (IDVal == ".mask")
5661 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
5662 else
5663 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00005664 return false;
5665 }
5666
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005667 if (IDVal == ".nan")
5668 return parseDirectiveNaN();
5669
Jack Carter07c818d2013-01-25 01:31:34 +00005670 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00005671 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00005672 return false;
5673 }
5674
Rafael Espindolab59fb732014-03-28 18:50:26 +00005675 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005676 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005677 return false;
5678 }
5679
Jack Carter07c818d2013-01-25 01:31:34 +00005680 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005681 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00005682 return false;
5683 }
5684
Jack Carter0cd3c192014-01-06 23:27:31 +00005685 if (IDVal == ".option")
5686 return parseDirectiveOption();
5687
5688 if (IDVal == ".abicalls") {
5689 getTargetStreamer().emitDirectiveAbiCalls();
5690 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005691 Error(Parser.getTok().getLoc(),
5692 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005693 // Clear line
5694 Parser.eatToEndOfStatement();
5695 }
5696 return false;
5697 }
5698
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005699 if (IDVal == ".cpsetup")
5700 return parseDirectiveCPSetup();
5701
Daniel Sandersf173dda2015-09-22 10:50:09 +00005702 if (IDVal == ".cpreturn")
5703 return parseDirectiveCPReturn();
5704
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005705 if (IDVal == ".module")
5706 return parseDirectiveModule();
5707
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00005708 if (IDVal == ".llvm_internal_mips_reallow_module_directive")
5709 return parseInternalDirectiveReallowModule();
5710
Toma Tabacu9ca50962015-04-16 09:53:47 +00005711 if (IDVal == ".insn")
5712 return parseInsnDirective();
5713
Rafael Espindola870c4e92012-01-11 03:56:41 +00005714 return true;
5715}
5716
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00005717bool MipsAsmParser::parseInternalDirectiveReallowModule() {
5718 // If this is not the end of the statement, report an error.
5719 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5720 reportParseError("unexpected token, expected end of statement");
5721 return false;
5722 }
5723
5724 getTargetStreamer().reallowModuleDirective();
5725
5726 getParser().Lex(); // Eat EndOfStatement token.
5727 return false;
5728}
5729
Rafael Espindola870c4e92012-01-11 03:56:41 +00005730extern "C" void LLVMInitializeMipsAsmParser() {
5731 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
5732 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
5733 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
5734 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
5735}
Jack Carterb4dbc172012-09-05 23:34:03 +00005736
5737#define GET_REGISTER_MATCHER
5738#define GET_MATCHER_IMPLEMENTATION
5739#include "MipsGenAsmMatcher.inc"