blob: 09ae6a5d43c72328d46b81fa6913ce044714359b [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
Daniel Sanders5bf6eab2015-10-26 23:50:00 +0000170 enum MacroExpanderResultTy {
171 MER_NotAMacro,
172 MER_Success,
173 MER_Fail,
174 };
Jack Carter30a59822012-10-04 04:03:53 +0000175
Matheus Almeida3813d572014-06-19 14:39:14 +0000176 // Expands assembly pseudo instructions.
Daniel Sanders5bf6eab2015-10-26 23:50:00 +0000177 MacroExpanderResultTy
178 tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
179 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000180
Toma Tabacu8f6603a2015-01-30 11:18:50 +0000181 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
182 SmallVectorImpl<MCInst> &Instructions);
183
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000184 bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000185 bool Is32BitImm, bool IsAddress, SMLoc IDLoc,
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000186 SmallVectorImpl<MCInst> &Instructions);
187
Toma Tabacuf712ede2015-06-17 14:31:51 +0000188 bool loadAndAddSymbolAddress(const MCExpr *SymExpr, unsigned DstReg,
189 unsigned SrcReg, bool Is32BitSym, SMLoc IDLoc,
190 SmallVectorImpl<MCInst> &Instructions);
Toma Tabacu674825c2015-06-16 12:16:24 +0000191
Toma Tabacu00e98672015-05-01 12:19:27 +0000192 bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000193 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000194
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000195 bool expandLoadAddress(unsigned DstReg, unsigned BaseReg,
196 const MCOperand &Offset, bool Is32BitAddress,
197 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000198
Jozef Kolek5cfebdd2015-01-21 12:39:30 +0000199 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
200 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000201
Jack Carter9e65aa32013-03-22 00:05:30 +0000202 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000203 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
204 bool isImmOpnd);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000205
206 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
207 SmallVectorImpl<MCInst> &Instructions);
208
Zoran Jovanoviccdb64562015-09-28 11:11:34 +0000209 bool expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
210 SmallVectorImpl<MCInst> &Instructions);
211
Toma Tabacue1e460d2015-06-11 10:36:10 +0000212 bool expandBranchImm(MCInst &Inst, SMLoc IDLoc,
213 SmallVectorImpl<MCInst> &Instructions);
214
Toma Tabacu1a108322015-06-17 13:20:24 +0000215 bool expandCondBranches(MCInst &Inst, SMLoc IDLoc,
216 SmallVectorImpl<MCInst> &Instructions);
217
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000218 bool expandDiv(MCInst &Inst, SMLoc IDLoc,
219 SmallVectorImpl<MCInst> &Instructions, const bool IsMips64,
220 const bool Signed);
221
Daniel Sanders6394ee52015-10-15 14:52:58 +0000222 bool expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
223 SmallVectorImpl<MCInst> &Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000224
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +0000225 bool expandUlw(MCInst &Inst, SMLoc IDLoc,
226 SmallVectorImpl<MCInst> &Instructions);
227
Toma Tabacu234482a2015-03-16 12:03:39 +0000228 void createNop(bool hasShortDelaySlot, SMLoc IDLoc,
229 SmallVectorImpl<MCInst> &Instructions);
230
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000231 void createAddu(unsigned DstReg, unsigned SrcReg, unsigned TrgReg,
Toma Tabacu0b3e9782015-06-23 14:00:54 +0000232 bool Is64Bit, SmallVectorImpl<MCInst> &Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000233
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000234 void createCpRestoreMemOp(bool IsLoad, int StackOffset, SMLoc IDLoc,
235 SmallVectorImpl<MCInst> &Instructions);
236
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000237 bool reportParseError(Twine ErrorMsg);
238 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000239
Jack Carterb5cf5902013-04-17 00:18:04 +0000240 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000241 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000242
Vladimir Medic4c299852013-11-06 11:27:05 +0000243 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000244
245 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000246 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000247 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000248 bool parseSetFeature(uint64_t Feature);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000249 bool isPicAndNotNxxAbi(); // Used by .cpload, .cprestore, and .cpsetup.
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000250 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000251 bool parseDirectiveCpRestore(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000252 bool parseDirectiveCPSetup();
Daniel Sandersf173dda2015-09-22 10:50:09 +0000253 bool parseDirectiveCPReturn();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000254 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000255 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000256 bool parseDirectiveOption();
Toma Tabacu9ca50962015-04-16 09:53:47 +0000257 bool parseInsnDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000258
259 bool parseSetAtDirective();
260 bool parseSetNoAtDirective();
261 bool parseSetMacroDirective();
262 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000263 bool parseSetMsaDirective();
264 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000265 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000266 bool parseSetReorderDirective();
267 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000268 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000269 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000270 bool parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +0000271 bool parseSetOddSPRegDirective();
272 bool parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000273 bool parseSetPopDirective();
274 bool parseSetPushDirective();
Toma Tabacu29696502015-06-02 09:48:04 +0000275 bool parseSetSoftFloatDirective();
276 bool parseSetHardFloatDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000277
Jack Carterd76b2372013-03-21 21:44:16 +0000278 bool parseSetAssignment();
279
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000280 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000281 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000282 bool parseDirectiveGpDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000283 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000284 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000285 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
286 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000287
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000288 bool parseInternalDirectiveReallowModule();
289
Jack Carterdc1e35d2012-09-06 20:00:02 +0000290 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000291
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000292 bool eatComma(StringRef ErrorStr);
293
Jack Carter1ac53222013-02-20 23:11:17 +0000294 int matchCPURegisterName(StringRef Symbol);
295
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000296 int matchHWRegsRegisterName(StringRef Symbol);
297
Jack Carter873c7242013-01-12 01:03:14 +0000298 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000299
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000300 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000301
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000302 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000303
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000304 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000305
Jack Carter5dc8ac92013-09-25 23:50:44 +0000306 int matchMSA128RegisterName(StringRef Name);
307
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000308 int matchMSA128CtrlRegisterName(StringRef Name);
309
Jack Carterd0bd6422013-04-18 00:41:53 +0000310 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000311
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000312 unsigned getGPR(int RegNo);
313
Toma Tabacu89a712b2015-04-15 10:48:56 +0000314 /// Returns the internal register number for the current AT. Also checks if
315 /// the current AT is unavailable (set to $0) and gives an error if it is.
316 /// This should be used in pseudo-instruction expansions which need AT.
317 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000318
319 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000320 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000321
322 // Helper function that checks if the value of a vector index is within the
323 // boundaries of accepted values for each RegisterKind
324 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
325 bool validateMSAIndex(int Val, int RegKind);
326
Daniel Sandersf0df2212014-08-04 12:20:00 +0000327 // Selects a new architecture by updating the FeatureBits with the necessary
328 // info including implied dependencies.
329 // Internally, it clears all the feature bits related to *any* architecture
330 // and selects the new one using the ToggleFeature functionality of the
331 // MCSubtargetInfo object that handles implied dependencies. The reason we
332 // clear all the arch related bits manually is because ToggleFeature only
333 // clears the features that imply the feature being cleared and not the
334 // features implied by the feature being cleared. This is easier to see
335 // with an example:
336 // --------------------------------------------------
337 // | Feature | Implies |
338 // | -------------------------------------------------|
339 // | FeatureMips1 | None |
340 // | FeatureMips2 | FeatureMips1 |
341 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
342 // | FeatureMips4 | FeatureMips3 |
343 // | ... | |
344 // --------------------------------------------------
345 //
346 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
347 // FeatureMipsGP64 | FeatureMips1)
348 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
349 void selectArch(StringRef ArchFeature) {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000350 FeatureBitset FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000351 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
352 STI.setFeatureBits(FeatureBits);
353 setAvailableFeatures(
354 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000355 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000356 }
357
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000358 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000359 if (!(STI.getFeatureBits()[Feature])) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000360 setAvailableFeatures(
361 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000362 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000363 }
364 }
365
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000366 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000367 if (STI.getFeatureBits()[Feature]) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000368 setAvailableFeatures(
369 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000370 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000371 }
372 }
373
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000374 void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
375 setFeatureBits(Feature, FeatureString);
376 AssemblerOptions.front()->setFeatures(STI.getFeatureBits());
377 }
378
379 void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
380 clearFeatureBits(Feature, FeatureString);
381 AssemblerOptions.front()->setFeatures(STI.getFeatureBits());
382 }
383
Rafael Espindola870c4e92012-01-11 03:56:41 +0000384public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000385 enum MipsMatchResultTy {
Daniel Sanders52da7af2015-11-06 12:11:03 +0000386 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY,
Matheus Almeida595fcab2014-06-11 15:05:56 +0000387#define GET_OPERAND_DIAGNOSTIC_TYPES
388#include "MipsGenAsmMatcher.inc"
389#undef GET_OPERAND_DIAGNOSTIC_TYPES
390
391 };
392
Joey Gouly0e76fa72013-09-12 10:28:05 +0000393 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000394 const MCInstrInfo &MII, const MCTargetOptions &Options)
Colin LeMahieufe2c8b82015-07-27 21:56:53 +0000395 : MCTargetAsmParser(Options), STI(sti),
Daniel Sanders50f17232015-09-15 16:17:27 +0000396 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
397 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000398 MCAsmParserExtension::Initialize(parser);
399
Toma Tabacu11e14a92015-04-21 11:50:52 +0000400 parser.addAliasForDirective(".asciiz", ".asciz");
401
Jack Carterb4dbc172012-09-05 23:34:03 +0000402 // Initialize the set of available features.
403 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000404
Toma Tabacu9db22db2014-09-09 10:15:38 +0000405 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000406 AssemblerOptions.push_back(
Toma Tabacu465acfd2015-06-09 13:33:26 +0000407 llvm::make_unique<MipsAssemblerOptions>(STI.getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000408
Toma Tabacu9db22db2014-09-09 10:15:38 +0000409 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000410 AssemblerOptions.push_back(
Toma Tabacu465acfd2015-06-09 13:33:26 +0000411 llvm::make_unique<MipsAssemblerOptions>(STI.getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000412
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000413 getTargetStreamer().updateABIInfo(*this);
414
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000415 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000416 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000417
418 CurrentFn = nullptr;
Toma Tabacud88d79c2015-06-23 14:39:42 +0000419
Daniel Sandersa6994442015-08-18 12:33:54 +0000420 IsPicEnabled =
421 (getContext().getObjectFileInfo()->getRelocM() == Reloc::PIC_);
422
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000423 IsCpRestoreSet = false;
424 CpRestoreOffset = -1;
425
Daniel Sanders50f17232015-09-15 16:17:27 +0000426 Triple TheTriple(sti.getTargetTriple());
427 if ((TheTriple.getArch() == Triple::mips) ||
428 (TheTriple.getArch() == Triple::mips64))
Toma Tabacud88d79c2015-06-23 14:39:42 +0000429 IsLittleEndian = false;
430 else
431 IsLittleEndian = true;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000432 }
433
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000434 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
435 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
436
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000437 bool isGP64bit() const { return STI.getFeatureBits()[Mips::FeatureGP64Bit]; }
438 bool isFP64bit() const { return STI.getFeatureBits()[Mips::FeatureFP64Bit]; }
Eric Christophera5762812015-01-26 17:33:46 +0000439 const MipsABIInfo &getABI() const { return ABI; }
440 bool isABI_N32() const { return ABI.IsN32(); }
441 bool isABI_N64() const { return ABI.IsN64(); }
442 bool isABI_O32() const { return ABI.IsO32(); }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000443 bool isABI_FPXX() const { return STI.getFeatureBits()[Mips::FeatureFPXX]; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000444
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000445 bool useOddSPReg() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000446 return !(STI.getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000447 }
448
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000449 bool inMicroMipsMode() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000450 return STI.getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000451 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000452 bool hasMips1() const { return STI.getFeatureBits()[Mips::FeatureMips1]; }
453 bool hasMips2() const { return STI.getFeatureBits()[Mips::FeatureMips2]; }
454 bool hasMips3() const { return STI.getFeatureBits()[Mips::FeatureMips3]; }
455 bool hasMips4() const { return STI.getFeatureBits()[Mips::FeatureMips4]; }
456 bool hasMips5() const { return STI.getFeatureBits()[Mips::FeatureMips5]; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000457 bool hasMips32() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000458 return STI.getFeatureBits()[Mips::FeatureMips32];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000459 }
460 bool hasMips64() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000461 return STI.getFeatureBits()[Mips::FeatureMips64];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000462 }
463 bool hasMips32r2() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000464 return STI.getFeatureBits()[Mips::FeatureMips32r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000465 }
466 bool hasMips64r2() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000467 return STI.getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000468 }
Daniel Sanders17793142015-02-18 16:24:50 +0000469 bool hasMips32r3() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000470 return (STI.getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000471 }
472 bool hasMips64r3() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000473 return (STI.getFeatureBits()[Mips::FeatureMips64r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000474 }
475 bool hasMips32r5() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000476 return (STI.getFeatureBits()[Mips::FeatureMips32r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000477 }
478 bool hasMips64r5() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000479 return (STI.getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000480 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000481 bool hasMips32r6() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000482 return STI.getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000483 }
484 bool hasMips64r6() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000485 return STI.getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000486 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000487
488 bool hasDSP() const { return STI.getFeatureBits()[Mips::FeatureDSP]; }
489 bool hasDSPR2() const { return STI.getFeatureBits()[Mips::FeatureDSPR2]; }
Zoran Jovanovic2e386d32015-10-12 16:07:25 +0000490 bool hasDSPR3() const { return STI.getFeatureBits()[Mips::FeatureDSPR3]; }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000491 bool hasMSA() const { return STI.getFeatureBits()[Mips::FeatureMSA]; }
Kai Nackee0245392015-01-27 19:11:28 +0000492 bool hasCnMips() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000493 return (STI.getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000494 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000495
Daniel Sandersa6994442015-08-18 12:33:54 +0000496 bool inPicMode() {
497 return IsPicEnabled;
498 }
499
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000500 bool inMips16Mode() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000501 return STI.getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000502 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000503
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000504 bool useTraps() const {
505 return STI.getFeatureBits()[Mips::FeatureUseTCCInDIV];
506 }
507
Eric Christophere8ae3e32015-05-07 23:10:21 +0000508 bool useSoftFloat() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000509 return STI.getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000510 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000511
Toma Tabacud9d344b2015-04-27 14:05:04 +0000512 /// Warn if RegIndex is the same as the current AT.
513 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000514
515 void warnIfNoMacro(SMLoc Loc);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000516
517 bool isLittle() const { return IsLittleEndian; }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000518};
519}
520
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000521namespace {
522
523/// MipsOperand - Instances of this class represent a parsed Mips machine
524/// instruction.
525class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000526public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000527 /// Broad categories of register classes
528 /// The exact class is finalized by the render method.
529 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000530 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000531 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000532 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000533 RegKind_FCC = 4, /// FCC
534 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
535 RegKind_MSACtrl = 16, /// MSA control registers
536 RegKind_COP2 = 32, /// COP2
537 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
538 /// context).
539 RegKind_CCR = 128, /// CCR
540 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000541 RegKind_COP3 = 512, /// COP3
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000542 RegKind_COP0 = 1024, /// COP0
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000543 /// Potentially any (e.g. $1)
544 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
545 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000546 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
Jack Carter873c7242013-01-12 01:03:14 +0000547 };
548
549private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000550 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000551 k_Immediate, /// An immediate (possibly involving symbol references)
552 k_Memory, /// Base + Offset Memory Address
553 k_PhysRegister, /// A physical register from the Mips namespace
554 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000555 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000556 k_RegList, /// A physical register list
557 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000558 } Kind;
559
David Blaikie960ea3f2014-06-08 16:18:35 +0000560public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000561 MipsOperand(KindTy K, MipsAsmParser &Parser)
562 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
563
David Blaikie960ea3f2014-06-08 16:18:35 +0000564private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000565 /// For diagnostics, and checking the assembler temporary
566 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000567
Eric Christopher8996c5d2013-03-15 00:42:55 +0000568 struct Token {
569 const char *Data;
570 unsigned Length;
571 };
572
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000573 struct PhysRegOp {
574 unsigned Num; /// Register Number
575 };
576
577 struct RegIdxOp {
578 unsigned Index; /// Index into the register class
579 RegKind Kind; /// Bitfield of the kinds it could possibly be
580 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000581 };
582
583 struct ImmOp {
584 const MCExpr *Val;
585 };
586
587 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000588 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000589 const MCExpr *Off;
590 };
591
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000592 struct RegListOp {
593 SmallVector<unsigned, 10> *List;
594 };
595
Jack Carterb4dbc172012-09-05 23:34:03 +0000596 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000597 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000598 struct PhysRegOp PhysReg;
599 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000600 struct ImmOp Imm;
601 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000602 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000603 };
604
605 SMLoc StartLoc, EndLoc;
606
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000607 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000608 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
609 const MCRegisterInfo *RegInfo,
610 SMLoc S, SMLoc E,
611 MipsAsmParser &Parser) {
612 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000613 Op->RegIdx.Index = Index;
614 Op->RegIdx.RegInfo = RegInfo;
615 Op->RegIdx.Kind = RegKind;
616 Op->StartLoc = S;
617 Op->EndLoc = E;
618 return Op;
619 }
620
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000621public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000622 /// Coerce the register to GPR32 and return the real register for the current
623 /// target.
624 unsigned getGPR32Reg() const {
625 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000626 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000627 unsigned ClassID = Mips::GPR32RegClassID;
628 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000629 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000630
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000631 /// Coerce the register to GPR32 and return the real register for the current
632 /// target.
633 unsigned getGPRMM16Reg() const {
634 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
635 unsigned ClassID = Mips::GPR32RegClassID;
636 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
637 }
638
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000639 /// Coerce the register to GPR64 and return the real register for the current
640 /// target.
641 unsigned getGPR64Reg() const {
642 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
643 unsigned ClassID = Mips::GPR64RegClassID;
644 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000645 }
646
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000647private:
648 /// Coerce the register to AFGR64 and return the real register for the current
649 /// target.
650 unsigned getAFGR64Reg() const {
651 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
652 if (RegIdx.Index % 2 != 0)
653 AsmParser.Warning(StartLoc, "Float register should be even.");
654 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
655 .getRegister(RegIdx.Index / 2);
656 }
657
658 /// Coerce the register to FGR64 and return the real register for the current
659 /// target.
660 unsigned getFGR64Reg() const {
661 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
662 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
663 .getRegister(RegIdx.Index);
664 }
665
666 /// Coerce the register to FGR32 and return the real register for the current
667 /// target.
668 unsigned getFGR32Reg() const {
669 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
670 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
671 .getRegister(RegIdx.Index);
672 }
673
674 /// Coerce the register to FGRH32 and return the real register for the current
675 /// target.
676 unsigned getFGRH32Reg() const {
677 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
678 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
679 .getRegister(RegIdx.Index);
680 }
681
682 /// Coerce the register to FCC and return the real register for the current
683 /// target.
684 unsigned getFCCReg() const {
685 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
686 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
687 .getRegister(RegIdx.Index);
688 }
689
690 /// Coerce the register to MSA128 and return the real register for the current
691 /// target.
692 unsigned getMSA128Reg() const {
693 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
694 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
695 // identical
696 unsigned ClassID = Mips::MSA128BRegClassID;
697 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
698 }
699
700 /// Coerce the register to MSACtrl and return the real register for the
701 /// current target.
702 unsigned getMSACtrlReg() const {
703 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
704 unsigned ClassID = Mips::MSACtrlRegClassID;
705 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
706 }
707
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000708 /// Coerce the register to COP0 and return the real register for the
709 /// current target.
710 unsigned getCOP0Reg() const {
711 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");
712 unsigned ClassID = Mips::COP0RegClassID;
713 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
714 }
715
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000716 /// Coerce the register to COP2 and return the real register for the
717 /// current target.
718 unsigned getCOP2Reg() const {
719 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
720 unsigned ClassID = Mips::COP2RegClassID;
721 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
722 }
723
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000724 /// Coerce the register to COP3 and return the real register for the
725 /// current target.
726 unsigned getCOP3Reg() const {
727 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
728 unsigned ClassID = Mips::COP3RegClassID;
729 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
730 }
731
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000732 /// Coerce the register to ACC64DSP and return the real register for the
733 /// current target.
734 unsigned getACC64DSPReg() const {
735 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
736 unsigned ClassID = Mips::ACC64DSPRegClassID;
737 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
738 }
739
740 /// Coerce the register to HI32DSP and return the real register for the
741 /// current target.
742 unsigned getHI32DSPReg() const {
743 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
744 unsigned ClassID = Mips::HI32DSPRegClassID;
745 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
746 }
747
748 /// Coerce the register to LO32DSP and return the real register for the
749 /// current target.
750 unsigned getLO32DSPReg() const {
751 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
752 unsigned ClassID = Mips::LO32DSPRegClassID;
753 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
754 }
755
756 /// Coerce the register to CCR and return the real register for the
757 /// current target.
758 unsigned getCCRReg() const {
759 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
760 unsigned ClassID = Mips::CCRRegClassID;
761 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
762 }
763
764 /// Coerce the register to HWRegs and return the real register for the
765 /// current target.
766 unsigned getHWRegsReg() const {
767 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
768 unsigned ClassID = Mips::HWRegsRegClassID;
769 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
770 }
771
772public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000773 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000774 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000775 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000776 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000777 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000778 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000779 else
Jim Grosbache9119e42015-05-13 18:37:00 +0000780 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000781 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000782
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000783 void addRegOperands(MCInst &Inst, unsigned N) const {
784 llvm_unreachable("Use a custom parser instead");
785 }
786
Daniel Sanders21bce302014-04-01 12:35:23 +0000787 /// Render the operand to an MCInst as a GPR32
788 /// Asserts if the wrong number of operands are requested, or the operand
789 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000790 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
791 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000792 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000793 }
794
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000795 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
796 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000797 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000798 }
799
Jozef Kolek1904fa22014-11-24 14:25:53 +0000800 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
801 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000802 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +0000803 }
804
Zoran Jovanovic41688672015-02-10 16:36:20 +0000805 void addGPRMM16AsmRegMovePOperands(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(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000808 }
809
Daniel Sanders21bce302014-04-01 12:35:23 +0000810 /// Render the operand to an MCInst as a GPR64
811 /// Asserts if the wrong number of operands are requested, or the operand
812 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000813 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
814 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000815 Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000816 }
817
818 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
819 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000820 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000821 }
822
823 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
824 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000825 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000826 }
827
828 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
829 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000830 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000831 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000832 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000833 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
834 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000835 }
836
837 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
838 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000839 Inst.addOperand(MCOperand::createReg(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000840 }
841
842 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
843 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000844 Inst.addOperand(MCOperand::createReg(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000845 }
846
847 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
848 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000849 Inst.addOperand(MCOperand::createReg(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000850 }
851
852 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
853 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000854 Inst.addOperand(MCOperand::createReg(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000855 }
856
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000857 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
858 assert(N == 1 && "Invalid number of operands!");
859 Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
860 }
861
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000862 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
863 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000864 Inst.addOperand(MCOperand::createReg(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000865 }
866
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000867 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
868 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000869 Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000870 }
871
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000872 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
873 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000874 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000875 }
876
877 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
878 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000879 Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000880 }
881
882 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
883 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000884 Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000885 }
886
887 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
888 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000889 Inst.addOperand(MCOperand::createReg(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000890 }
891
892 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
893 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000894 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000895 }
896
Daniel Sanders52da7af2015-11-06 12:11:03 +0000897 template <unsigned Bits>
898 void addConstantUImmOperands(MCInst &Inst, unsigned N) const {
899 assert(N == 1 && "Invalid number of operands!");
900 uint64_t Imm = getConstantImm() & ((1 << Bits) - 1);
901 Inst.addOperand(MCOperand::createImm(Imm));
902 }
903
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000904 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000905 assert(N == 1 && "Invalid number of operands!");
906 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000907 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000908 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000909
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000910 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000911 assert(N == 2 && "Invalid number of operands!");
912
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000913 Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
914 ? getMemBase()->getGPR64Reg()
915 : getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000916
917 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000918 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000919 }
920
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000921 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
922 assert(N == 2 && "Invalid number of operands!");
923
Jim Grosbache9119e42015-05-13 18:37:00 +0000924 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000925
926 const MCExpr *Expr = getMemOff();
927 addExpr(Inst, Expr);
928 }
929
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000930 void addRegListOperands(MCInst &Inst, unsigned N) const {
931 assert(N == 1 && "Invalid number of operands!");
932
933 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000934 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000935 }
936
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000937 void addRegPairOperands(MCInst &Inst, unsigned N) const {
938 assert(N == 2 && "Invalid number of operands!");
939 unsigned RegNo = getRegPair();
Jim Grosbache9119e42015-05-13 18:37:00 +0000940 Inst.addOperand(MCOperand::createReg(RegNo++));
941 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000942 }
943
Zoran Jovanovic41688672015-02-10 16:36:20 +0000944 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
945 assert(N == 2 && "Invalid number of operands!");
946 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000947 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000948 }
949
Craig Topper56c590a2014-04-29 07:58:02 +0000950 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000951 // As a special case until we sort out the definition of div/divu, pretend
952 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
953 if (isGPRAsmReg() && RegIdx.Index == 0)
954 return true;
955
956 return Kind == k_PhysRegister;
957 }
958 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000959 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000960 bool isConstantImm() const {
961 return isImm() && dyn_cast<MCConstantExpr>(getImm());
962 }
Daniel Sanders52da7af2015-11-06 12:11:03 +0000963 bool isConstantImmz() const {
964 return isConstantImm() && getConstantImm() == 0;
965 }
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +0000966 template <unsigned Bits> bool isUImm() const {
967 return isImm() && isConstantImm() && isUInt<Bits>(getConstantImm());
968 }
Craig Topper56c590a2014-04-29 07:58:02 +0000969 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000970 // Note: It's not possible to pretend that other operand kinds are tokens.
971 // The matcher emitter checks tokens first.
972 return Kind == k_Token;
973 }
Craig Topper56c590a2014-04-29 07:58:02 +0000974 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000975 bool isConstantMemOff() const {
976 return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
977 }
978 template <unsigned Bits> bool isMemWithSimmOffset() const {
Zoran Jovanovica6593ff2015-08-18 12:53:08 +0000979 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
980 && getMemBase()->isGPRAsmReg();
981 }
Zoran Jovanovic6e6a2c92015-09-16 09:14:35 +0000982 template <unsigned Bits> bool isMemWithSimmOffsetGPR() const {
983 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff()) &&
984 getMemBase()->isGPRAsmReg();
985 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000986 bool isMemWithGRPMM16Base() const {
987 return isMem() && getMemBase()->isMM16AsmReg();
988 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000989 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
990 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
991 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
992 }
Jozef Kolek12c69822014-12-23 16:16:33 +0000993 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
994 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
995 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
996 && (getMemBase()->getGPR32Reg() == Mips::SP);
997 }
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +0000998 bool isUImm5Lsl2() const {
999 return (isImm() && isConstantImm() && isShiftedUInt<5, 2>(getConstantImm()));
1000 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001001 bool isRegList16() const {
1002 if (!isRegList())
1003 return false;
1004
1005 int Size = RegList.List->size();
1006 if (Size < 2 || Size > 5 || *RegList.List->begin() != Mips::S0 ||
1007 RegList.List->back() != Mips::RA)
1008 return false;
1009
1010 int PrevReg = *RegList.List->begin();
1011 for (int i = 1; i < Size - 1; i++) {
1012 int Reg = (*(RegList.List))[i];
1013 if ( Reg != PrevReg + 1)
1014 return false;
1015 PrevReg = Reg;
1016 }
1017
1018 return true;
1019 }
Vladimir Medic2b953d02013-10-01 09:48:56 +00001020 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001021 bool isLSAImm() const {
1022 if (!isConstantImm())
1023 return false;
1024 int64_t Val = getConstantImm();
1025 return 1 <= Val && Val <= 4;
1026 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001027 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001028 bool isMovePRegPair() const {
1029 if (Kind != k_RegList || RegList.List->size() != 2)
1030 return false;
1031
1032 unsigned R0 = RegList.List->front();
1033 unsigned R1 = RegList.List->back();
1034
1035 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
1036 (R0 == Mips::A1 && R1 == Mips::A3) ||
1037 (R0 == Mips::A2 && R1 == Mips::A3) ||
1038 (R0 == Mips::A0 && R1 == Mips::S5) ||
1039 (R0 == Mips::A0 && R1 == Mips::S6) ||
1040 (R0 == Mips::A0 && R1 == Mips::A1) ||
1041 (R0 == Mips::A0 && R1 == Mips::A2) ||
1042 (R0 == Mips::A0 && R1 == Mips::A3))
1043 return true;
1044
1045 return false;
1046 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001047
1048 StringRef getToken() const {
1049 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001050 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001051 }
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001052 bool isRegPair() const { return Kind == k_RegPair; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001053
Craig Topper56c590a2014-04-29 07:58:02 +00001054 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001055 // As a special case until we sort out the definition of div/divu, pretend
1056 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
1057 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1058 RegIdx.Kind & RegKind_GPR)
1059 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001060
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001061 assert(Kind == k_PhysRegister && "Invalid access!");
1062 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +00001063 }
1064
Jack Carterb4dbc172012-09-05 23:34:03 +00001065 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001066 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001067 return Imm.Val;
1068 }
1069
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001070 int64_t getConstantImm() const {
1071 const MCExpr *Val = getImm();
1072 return static_cast<const MCConstantExpr *>(Val)->getValue();
1073 }
1074
1075 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001076 assert((Kind == k_Memory) && "Invalid access!");
1077 return Mem.Base;
1078 }
1079
1080 const MCExpr *getMemOff() const {
1081 assert((Kind == k_Memory) && "Invalid access!");
1082 return Mem.Off;
1083 }
1084
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001085 int64_t getConstantMemOff() const {
1086 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1087 }
1088
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001089 const SmallVectorImpl<unsigned> &getRegList() const {
1090 assert((Kind == k_RegList) && "Invalid access!");
1091 return *(RegList.List);
1092 }
1093
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001094 unsigned getRegPair() const {
1095 assert((Kind == k_RegPair) && "Invalid access!");
1096 return RegIdx.Index;
1097 }
1098
David Blaikie960ea3f2014-06-08 16:18:35 +00001099 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1100 MipsAsmParser &Parser) {
1101 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001102 Op->Tok.Data = Str.data();
1103 Op->Tok.Length = Str.size();
1104 Op->StartLoc = S;
1105 Op->EndLoc = S;
1106 return Op;
1107 }
1108
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001109 /// Create a numeric register (e.g. $1). The exact register remains
1110 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001111 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001112 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001113 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001114 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001115 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001116 }
1117
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001118 /// Create a register that is definitely a GPR.
1119 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001120 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001121 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001122 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001123 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001124 }
1125
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001126 /// Create a register that is definitely a FGR.
1127 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001128 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001129 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001130 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001131 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
1132 }
1133
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001134 /// Create a register that is definitely a HWReg.
1135 /// This is typically only used for named registers such as $hwr_cpunum.
1136 static std::unique_ptr<MipsOperand>
1137 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
1138 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1139 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
1140 }
1141
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001142 /// Create a register that is definitely an FCC.
1143 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001144 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001145 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001146 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001147 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
1148 }
1149
1150 /// Create a register that is definitely an ACC.
1151 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001152 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001153 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001154 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001155 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
1156 }
1157
1158 /// Create a register that is definitely an MSA128.
1159 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001160 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001161 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001162 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001163 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
1164 }
1165
1166 /// Create a register that is definitely an MSACtrl.
1167 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001168 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001169 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001170 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001171 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
1172 }
1173
David Blaikie960ea3f2014-06-08 16:18:35 +00001174 static std::unique_ptr<MipsOperand>
1175 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1176 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001177 Op->Imm.Val = Val;
1178 Op->StartLoc = S;
1179 Op->EndLoc = E;
1180 return Op;
1181 }
1182
David Blaikie960ea3f2014-06-08 16:18:35 +00001183 static std::unique_ptr<MipsOperand>
1184 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1185 SMLoc E, MipsAsmParser &Parser) {
1186 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1187 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001188 Op->Mem.Off = Off;
1189 Op->StartLoc = S;
1190 Op->EndLoc = E;
1191 return Op;
1192 }
1193
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001194 static std::unique_ptr<MipsOperand>
1195 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1196 MipsAsmParser &Parser) {
1197 assert (Regs.size() > 0 && "Empty list not allowed");
1198
1199 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001200 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001201 Op->StartLoc = StartLoc;
1202 Op->EndLoc = EndLoc;
1203 return Op;
1204 }
1205
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001206 static std::unique_ptr<MipsOperand>
1207 CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1208 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
1209 Op->RegIdx.Index = RegNo;
1210 Op->StartLoc = S;
1211 Op->EndLoc = E;
1212 return Op;
1213 }
1214
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001215 bool isGPRAsmReg() const {
1216 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001217 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001218 bool isMM16AsmReg() const {
1219 if (!(isRegIdx() && RegIdx.Kind))
1220 return false;
1221 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1222 || RegIdx.Index == 16 || RegIdx.Index == 17);
1223 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001224 bool isMM16AsmRegZero() const {
1225 if (!(isRegIdx() && RegIdx.Kind))
1226 return false;
1227 return (RegIdx.Index == 0 ||
1228 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1229 RegIdx.Index == 17);
1230 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001231 bool isMM16AsmRegMoveP() const {
1232 if (!(isRegIdx() && RegIdx.Kind))
1233 return false;
1234 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1235 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1236 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001237 bool isFGRAsmReg() const {
1238 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1239 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001240 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001241 bool isHWRegsAsmReg() const {
1242 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001243 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001244 bool isCCRAsmReg() const {
1245 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001246 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001247 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001248 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1249 return false;
1250 if (!AsmParser.hasEightFccRegisters())
1251 return RegIdx.Index == 0;
1252 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001253 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001254 bool isACCAsmReg() const {
1255 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001256 }
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001257 bool isCOP0AsmReg() const {
1258 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1259 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001260 bool isCOP2AsmReg() const {
1261 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001262 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001263 bool isCOP3AsmReg() const {
1264 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1265 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001266 bool isMSA128AsmReg() const {
1267 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001268 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001269 bool isMSACtrlAsmReg() const {
1270 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001271 }
1272
Jack Carterb4dbc172012-09-05 23:34:03 +00001273 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001274 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001275 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001276 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001277
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001278 virtual ~MipsOperand() {
1279 switch (Kind) {
1280 case k_Immediate:
1281 break;
1282 case k_Memory:
1283 delete Mem.Base;
1284 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001285 case k_RegList:
1286 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001287 case k_PhysRegister:
1288 case k_RegisterIndex:
1289 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001290 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001291 break;
1292 }
1293 }
1294
Craig Topper56c590a2014-04-29 07:58:02 +00001295 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001296 switch (Kind) {
1297 case k_Immediate:
1298 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001299 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001300 OS << ">";
1301 break;
1302 case k_Memory:
1303 OS << "Mem<";
1304 Mem.Base->print(OS);
1305 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001306 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001307 OS << ">";
1308 break;
1309 case k_PhysRegister:
1310 OS << "PhysReg<" << PhysReg.Num << ">";
1311 break;
1312 case k_RegisterIndex:
1313 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1314 break;
1315 case k_Token:
1316 OS << Tok.Data;
1317 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001318 case k_RegList:
1319 OS << "RegList< ";
1320 for (auto Reg : (*RegList.List))
1321 OS << Reg << " ";
1322 OS << ">";
1323 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001324 case k_RegPair:
1325 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1326 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001327 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001328 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001329}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001330} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001331
Jack Carter9e65aa32013-03-22 00:05:30 +00001332namespace llvm {
1333extern const MCInstrDesc MipsInsts[];
1334}
1335static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1336 return MipsInsts[Opcode];
1337}
1338
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001339static bool hasShortDelaySlot(unsigned Opcode) {
1340 switch (Opcode) {
1341 case Mips::JALS_MM:
1342 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001343 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001344 case Mips::BGEZALS_MM:
1345 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001346 return true;
1347 default:
1348 return false;
1349 }
1350}
1351
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001352static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1353 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1354 return &SRExpr->getSymbol();
1355 }
1356
1357 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1358 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1359 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1360
1361 if (LHSSym)
1362 return LHSSym;
1363
1364 if (RHSSym)
1365 return RHSSym;
1366
1367 return nullptr;
1368 }
1369
1370 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1371 return getSingleMCSymbol(UExpr->getSubExpr());
1372
1373 return nullptr;
1374}
1375
1376static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1377 if (isa<MCSymbolRefExpr>(Expr))
1378 return 1;
1379
1380 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1381 return countMCSymbolRefExpr(BExpr->getLHS()) +
1382 countMCSymbolRefExpr(BExpr->getRHS());
1383
1384 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1385 return countMCSymbolRefExpr(UExpr->getSubExpr());
1386
1387 return 0;
1388}
1389
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001390namespace {
1391void emitRX(unsigned Opcode, unsigned Reg0, MCOperand Op1, SMLoc IDLoc,
1392 SmallVectorImpl<MCInst> &Instructions) {
1393 MCInst tmpInst;
1394 tmpInst.setOpcode(Opcode);
1395 tmpInst.addOperand(MCOperand::createReg(Reg0));
1396 tmpInst.addOperand(Op1);
1397 tmpInst.setLoc(IDLoc);
1398 Instructions.push_back(tmpInst);
1399}
1400
1401void emitRI(unsigned Opcode, unsigned Reg0, int32_t Imm, SMLoc IDLoc,
1402 SmallVectorImpl<MCInst> &Instructions) {
1403 emitRX(Opcode, Reg0, MCOperand::createImm(Imm), IDLoc, Instructions);
1404}
1405
1406void emitRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, SMLoc IDLoc,
1407 SmallVectorImpl<MCInst> &Instructions) {
1408 emitRX(Opcode, Reg0, MCOperand::createReg(Reg1), IDLoc, Instructions);
1409}
1410
1411void emitII(unsigned Opcode, int16_t Imm1, int16_t Imm2, SMLoc IDLoc,
1412 SmallVectorImpl<MCInst> &Instructions) {
1413 MCInst tmpInst;
1414 tmpInst.setOpcode(Opcode);
1415 tmpInst.addOperand(MCOperand::createImm(Imm1));
1416 tmpInst.addOperand(MCOperand::createImm(Imm2));
1417 tmpInst.setLoc(IDLoc);
1418 Instructions.push_back(tmpInst);
1419}
1420
1421void emitR(unsigned Opcode, unsigned Reg0, SMLoc IDLoc,
1422 SmallVectorImpl<MCInst> &Instructions) {
1423 MCInst tmpInst;
1424 tmpInst.setOpcode(Opcode);
1425 tmpInst.addOperand(MCOperand::createReg(Reg0));
1426 tmpInst.setLoc(IDLoc);
1427 Instructions.push_back(tmpInst);
1428}
1429
1430void emitRRX(unsigned Opcode, unsigned Reg0, unsigned Reg1, MCOperand Op2,
1431 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1432 MCInst tmpInst;
1433 tmpInst.setOpcode(Opcode);
1434 tmpInst.addOperand(MCOperand::createReg(Reg0));
1435 tmpInst.addOperand(MCOperand::createReg(Reg1));
1436 tmpInst.addOperand(Op2);
1437 tmpInst.setLoc(IDLoc);
1438 Instructions.push_back(tmpInst);
1439}
1440
1441void emitRRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, unsigned Reg2,
1442 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1443 emitRRX(Opcode, Reg0, Reg1, MCOperand::createReg(Reg2), IDLoc,
1444 Instructions);
1445}
1446
1447void emitRRI(unsigned Opcode, unsigned Reg0, unsigned Reg1, int16_t Imm,
1448 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1449 emitRRX(Opcode, Reg0, Reg1, MCOperand::createImm(Imm), IDLoc,
1450 Instructions);
1451}
1452
1453void emitAppropriateDSLL(unsigned DstReg, unsigned SrcReg, int16_t ShiftAmount,
1454 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1455 if (ShiftAmount >= 32) {
1456 emitRRI(Mips::DSLL32, DstReg, SrcReg, ShiftAmount - 32, IDLoc,
1457 Instructions);
1458 return;
1459 }
1460
1461 emitRRI(Mips::DSLL, DstReg, SrcReg, ShiftAmount, IDLoc, Instructions);
1462}
1463} // end anonymous namespace.
1464
Jack Carter9e65aa32013-03-22 00:05:30 +00001465bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001466 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001467 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001468 bool ExpandedJalSym = false;
Daniel Sandersa771fef2014-03-24 14:05:39 +00001469
Jack Carter9e65aa32013-03-22 00:05:30 +00001470 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001471
1472 if (MCID.isBranch() || MCID.isCall()) {
1473 const unsigned Opcode = Inst.getOpcode();
1474 MCOperand Offset;
1475
1476 switch (Opcode) {
1477 default:
1478 break;
Kai Nackee0245392015-01-27 19:11:28 +00001479 case Mips::BBIT0:
1480 case Mips::BBIT032:
1481 case Mips::BBIT1:
1482 case Mips::BBIT132:
1483 assert(hasCnMips() && "instruction only valid for octeon cpus");
1484 // Fall through
1485
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001486 case Mips::BEQ:
1487 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001488 case Mips::BEQ_MM:
1489 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001490 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001491 Offset = Inst.getOperand(2);
1492 if (!Offset.isImm())
1493 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001494 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001495 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001496 if (OffsetToAlignment(Offset.getImm(),
1497 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001498 return Error(IDLoc, "branch to misaligned address");
1499 break;
1500 case Mips::BGEZ:
1501 case Mips::BGTZ:
1502 case Mips::BLEZ:
1503 case Mips::BLTZ:
1504 case Mips::BGEZAL:
1505 case Mips::BLTZAL:
1506 case Mips::BC1F:
1507 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001508 case Mips::BGEZ_MM:
1509 case Mips::BGTZ_MM:
1510 case Mips::BLEZ_MM:
1511 case Mips::BLTZ_MM:
1512 case Mips::BGEZAL_MM:
1513 case Mips::BLTZAL_MM:
1514 case Mips::BC1F_MM:
1515 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001516 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001517 Offset = Inst.getOperand(1);
1518 if (!Offset.isImm())
1519 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001520 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001521 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001522 if (OffsetToAlignment(Offset.getImm(),
1523 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001524 return Error(IDLoc, "branch to misaligned address");
1525 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001526 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001527 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001528 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001529 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001530 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1531 Offset = Inst.getOperand(1);
1532 if (!Offset.isImm())
1533 break; // We'll deal with this situation later on when applying fixups.
Craig Topper55b1f292015-10-10 20:17:07 +00001534 if (!isInt<8>(Offset.getImm()))
Jozef Kolek9761e962015-01-12 12:03:34 +00001535 return Error(IDLoc, "branch target out of range");
1536 if (OffsetToAlignment(Offset.getImm(), 2LL))
1537 return Error(IDLoc, "branch to misaligned address");
1538 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001539 }
1540 }
1541
Daniel Sandersa84989a2014-06-16 13:25:35 +00001542 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1543 // We still accept it but it is a normal nop.
1544 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1545 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1546 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1547 "nop instruction");
1548 }
1549
Kai Nackee0245392015-01-27 19:11:28 +00001550 if (hasCnMips()) {
1551 const unsigned Opcode = Inst.getOpcode();
1552 MCOperand Opnd;
1553 int Imm;
1554
1555 switch (Opcode) {
1556 default:
1557 break;
1558
1559 case Mips::BBIT0:
1560 case Mips::BBIT032:
1561 case Mips::BBIT1:
1562 case Mips::BBIT132:
1563 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1564 // The offset is handled above
1565 Opnd = Inst.getOperand(1);
1566 if (!Opnd.isImm())
1567 return Error(IDLoc, "expected immediate operand kind");
1568 Imm = Opnd.getImm();
1569 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1570 Opcode == Mips::BBIT1 ? 63 : 31))
1571 return Error(IDLoc, "immediate operand value out of range");
1572 if (Imm > 31) {
1573 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1574 : Mips::BBIT132);
1575 Inst.getOperand(1).setImm(Imm - 32);
1576 }
1577 break;
1578
1579 case Mips::CINS:
1580 case Mips::CINS32:
1581 case Mips::EXTS:
1582 case Mips::EXTS32:
1583 assert(MCID.getNumOperands() == 4 && "unexpected number of operands");
1584 // Check length
1585 Opnd = Inst.getOperand(3);
1586 if (!Opnd.isImm())
1587 return Error(IDLoc, "expected immediate operand kind");
1588 Imm = Opnd.getImm();
1589 if (Imm < 0 || Imm > 31)
1590 return Error(IDLoc, "immediate operand value out of range");
1591 // Check position
1592 Opnd = Inst.getOperand(2);
1593 if (!Opnd.isImm())
1594 return Error(IDLoc, "expected immediate operand kind");
1595 Imm = Opnd.getImm();
1596 if (Imm < 0 || Imm > (Opcode == Mips::CINS ||
1597 Opcode == Mips::EXTS ? 63 : 31))
1598 return Error(IDLoc, "immediate operand value out of range");
1599 if (Imm > 31) {
1600 Inst.setOpcode(Opcode == Mips::CINS ? Mips::CINS32 : Mips::EXTS32);
1601 Inst.getOperand(2).setImm(Imm - 32);
1602 }
1603 break;
1604
1605 case Mips::SEQi:
1606 case Mips::SNEi:
1607 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1608 Opnd = Inst.getOperand(2);
1609 if (!Opnd.isImm())
1610 return Error(IDLoc, "expected immediate operand kind");
1611 Imm = Opnd.getImm();
1612 if (!isInt<10>(Imm))
1613 return Error(IDLoc, "immediate operand value out of range");
1614 break;
1615 }
1616 }
1617
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001618 // This expansion is not in a function called by tryExpandInstruction()
1619 // because the pseudo-instruction doesn't have a distinct opcode.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001620 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
1621 inPicMode()) {
1622 warnIfNoMacro(IDLoc);
1623
1624 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
1625
1626 // We can do this expansion if there's only 1 symbol in the argument
1627 // expression.
1628 if (countMCSymbolRefExpr(JalExpr) > 1)
1629 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
1630
1631 // FIXME: This is checking the expression can be handled by the later stages
1632 // of the assembler. We ought to leave it to those later stages but
1633 // we can't do that until we stop evaluateRelocExpr() rewriting the
1634 // expressions into non-equivalent forms.
1635 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
1636
1637 // FIXME: Add support for label+offset operands (currently causes an error).
1638 // FIXME: Add support for forward-declared local symbols.
1639 // FIXME: Add expansion for when the LargeGOT option is enabled.
1640 if (JalSym->isInSection() || JalSym->isTemporary()) {
1641 if (isABI_O32()) {
1642 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001643 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001644 // R_(MICRO)MIPS_GOT16 label
1645 // addiu $25, $25, 0
1646 // R_(MICRO)MIPS_LO16 label
1647 // jalr $25
1648 const MCExpr *Got16RelocExpr = evaluateRelocExpr(JalExpr, "got");
1649 const MCExpr *Lo16RelocExpr = evaluateRelocExpr(JalExpr, "lo");
1650
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001651 emitRRX(Mips::LW, Mips::T9, Mips::GP,
1652 MCOperand::createExpr(Got16RelocExpr), IDLoc, Instructions);
1653 emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
1654 MCOperand::createExpr(Lo16RelocExpr), IDLoc, Instructions);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001655 } else if (isABI_N32() || isABI_N64()) {
1656 // If it's a local symbol and the N32/N64 ABIs are being used,
1657 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001658 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001659 // R_(MICRO)MIPS_GOT_DISP label
1660 // jalr $25
1661 const MCExpr *GotDispRelocExpr = evaluateRelocExpr(JalExpr, "got_disp");
1662
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001663 emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
1664 MCOperand::createExpr(GotDispRelocExpr), IDLoc, Instructions);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001665 }
1666 } else {
1667 // If it's an external/weak symbol, we expand to:
1668 // lw/ld $25, 0($gp)
1669 // R_(MICRO)MIPS_CALL16 label
1670 // jalr $25
1671 const MCExpr *Call16RelocExpr = evaluateRelocExpr(JalExpr, "call16");
1672
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001673 emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
1674 MCOperand::createExpr(Call16RelocExpr), IDLoc, Instructions);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001675 }
1676
1677 MCInst JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001678 if (IsCpRestoreSet && inMicroMipsMode())
1679 JalrInst.setOpcode(Mips::JALRS_MM);
1680 else
1681 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001682 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
1683 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
1684
1685 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
1686 // This relocation is supposed to be an optimization hint for the linker
1687 // and is not necessary for correctness.
1688
1689 Inst = JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001690 ExpandedJalSym = true;
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001691 }
1692
Jack Carter9e65aa32013-03-22 00:05:30 +00001693 if (MCID.mayLoad() || MCID.mayStore()) {
1694 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001695 // reference or immediate we may have to expand instructions.
1696 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001697 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001698 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1699 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001700 MCOperand &Op = Inst.getOperand(i);
1701 if (Op.isImm()) {
1702 int MemOffset = Op.getImm();
1703 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001704 // Offset can't exceed 16bit value.
1705 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001706 return false;
1707 }
1708 } else if (Op.isExpr()) {
1709 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001710 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001711 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001712 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001713 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001714 // Expand symbol.
1715 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001716 return false;
1717 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001718 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001719 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001720 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001721 }
1722 }
1723 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001724 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001725 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001726
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001727 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001728 if (MCID.mayLoad()) {
1729 // Try to create 16-bit GP relative load instruction.
1730 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1731 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1732 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1733 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1734 MCOperand &Op = Inst.getOperand(i);
1735 if (Op.isImm()) {
1736 int MemOffset = Op.getImm();
1737 MCOperand &DstReg = Inst.getOperand(0);
1738 MCOperand &BaseReg = Inst.getOperand(1);
Craig Topper55b1f292015-10-10 20:17:07 +00001739 if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&
Jozef Koleke10a02e2015-01-28 17:27:26 +00001740 getContext().getRegisterInfo()->getRegClass(
1741 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00001742 (BaseReg.getReg() == Mips::GP ||
1743 BaseReg.getReg() == Mips::GP_64)) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001744
1745 emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
1746 IDLoc, Instructions);
Jozef Koleke10a02e2015-01-28 17:27:26 +00001747 return false;
1748 }
1749 }
1750 }
1751 } // for
1752 } // if load
1753
1754 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1755
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001756 MCOperand Opnd;
1757 int Imm;
1758
1759 switch (Inst.getOpcode()) {
1760 default:
1761 break;
1762 case Mips::ADDIUS5_MM:
1763 Opnd = Inst.getOperand(2);
1764 if (!Opnd.isImm())
1765 return Error(IDLoc, "expected immediate operand kind");
1766 Imm = Opnd.getImm();
1767 if (Imm < -8 || Imm > 7)
1768 return Error(IDLoc, "immediate operand value out of range");
1769 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001770 case Mips::ADDIUSP_MM:
1771 Opnd = Inst.getOperand(0);
1772 if (!Opnd.isImm())
1773 return Error(IDLoc, "expected immediate operand kind");
1774 Imm = Opnd.getImm();
1775 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1776 Imm % 4 != 0)
1777 return Error(IDLoc, "immediate operand value out of range");
1778 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001779 case Mips::SLL16_MM:
1780 case Mips::SRL16_MM:
1781 Opnd = Inst.getOperand(2);
1782 if (!Opnd.isImm())
1783 return Error(IDLoc, "expected immediate operand kind");
1784 Imm = Opnd.getImm();
1785 if (Imm < 1 || Imm > 8)
1786 return Error(IDLoc, "immediate operand value out of range");
1787 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001788 case Mips::LI16_MM:
1789 Opnd = Inst.getOperand(1);
1790 if (!Opnd.isImm())
1791 return Error(IDLoc, "expected immediate operand kind");
1792 Imm = Opnd.getImm();
1793 if (Imm < -1 || Imm > 126)
1794 return Error(IDLoc, "immediate operand value out of range");
1795 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001796 case Mips::ADDIUR2_MM:
1797 Opnd = Inst.getOperand(2);
1798 if (!Opnd.isImm())
1799 return Error(IDLoc, "expected immediate operand kind");
1800 Imm = Opnd.getImm();
1801 if (!(Imm == 1 || Imm == -1 ||
1802 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1803 return Error(IDLoc, "immediate operand value out of range");
1804 break;
Zoran Jovanovic42b84442014-10-23 11:13:59 +00001805 case Mips::ADDIUR1SP_MM:
1806 Opnd = Inst.getOperand(1);
1807 if (!Opnd.isImm())
1808 return Error(IDLoc, "expected immediate operand kind");
1809 Imm = Opnd.getImm();
1810 if (OffsetToAlignment(Imm, 4LL))
1811 return Error(IDLoc, "misaligned immediate operand value");
1812 if (Imm < 0 || Imm > 255)
1813 return Error(IDLoc, "immediate operand value out of range");
1814 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001815 case Mips::ANDI16_MM:
1816 Opnd = Inst.getOperand(2);
1817 if (!Opnd.isImm())
1818 return Error(IDLoc, "expected immediate operand kind");
1819 Imm = Opnd.getImm();
1820 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1821 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1822 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1823 return Error(IDLoc, "immediate operand value out of range");
1824 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001825 case Mips::LBU16_MM:
1826 Opnd = Inst.getOperand(2);
1827 if (!Opnd.isImm())
1828 return Error(IDLoc, "expected immediate operand kind");
1829 Imm = Opnd.getImm();
1830 if (Imm < -1 || Imm > 14)
1831 return Error(IDLoc, "immediate operand value out of range");
1832 break;
Zoran Jovanovic7ba636c2015-09-17 10:14:09 +00001833 case Mips::TEQ_MM:
1834 case Mips::TGE_MM:
1835 case Mips::TGEU_MM:
1836 case Mips::TLT_MM:
1837 case Mips::TLTU_MM:
1838 case Mips::TNE_MM:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001839 case Mips::SB16_MM:
1840 Opnd = Inst.getOperand(2);
1841 if (!Opnd.isImm())
1842 return Error(IDLoc, "expected immediate operand kind");
1843 Imm = Opnd.getImm();
1844 if (Imm < 0 || Imm > 15)
1845 return Error(IDLoc, "immediate operand value out of range");
1846 break;
1847 case Mips::LHU16_MM:
1848 case Mips::SH16_MM:
1849 Opnd = Inst.getOperand(2);
1850 if (!Opnd.isImm())
1851 return Error(IDLoc, "expected immediate operand kind");
1852 Imm = Opnd.getImm();
1853 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1854 return Error(IDLoc, "immediate operand value out of range");
1855 break;
1856 case Mips::LW16_MM:
1857 case Mips::SW16_MM:
1858 Opnd = Inst.getOperand(2);
1859 if (!Opnd.isImm())
1860 return Error(IDLoc, "expected immediate operand kind");
1861 Imm = Opnd.getImm();
1862 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1863 return Error(IDLoc, "immediate operand value out of range");
1864 break;
Zoran Jovanovic6e6a2c92015-09-16 09:14:35 +00001865 case Mips::PREFX_MM:
Jozef Kolekab6d1cc2014-12-23 19:55:34 +00001866 case Mips::CACHE:
1867 case Mips::PREF:
1868 Opnd = Inst.getOperand(2);
1869 if (!Opnd.isImm())
1870 return Error(IDLoc, "expected immediate operand kind");
1871 Imm = Opnd.getImm();
1872 if (!isUInt<5>(Imm))
1873 return Error(IDLoc, "immediate operand value out of range");
1874 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001875 case Mips::ADDIUPC_MM:
1876 MCOperand Opnd = Inst.getOperand(1);
1877 if (!Opnd.isImm())
1878 return Error(IDLoc, "expected immediate operand kind");
1879 int Imm = Opnd.getImm();
Craig Topper55b1f292015-10-10 20:17:07 +00001880 if ((Imm % 4 != 0) || !isInt<25>(Imm))
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001881 return Error(IDLoc, "immediate operand value out of range");
1882 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001883 }
1884 }
1885
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001886 MacroExpanderResultTy ExpandResult =
1887 tryExpandInstruction(Inst, IDLoc, Instructions);
1888 switch (ExpandResult) {
1889 case MER_NotAMacro:
Jack Carter9e65aa32013-03-22 00:05:30 +00001890 Instructions.push_back(Inst);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001891 break;
1892 case MER_Success:
1893 break;
1894 case MER_Fail:
1895 return true;
1896 }
Jack Carter9e65aa32013-03-22 00:05:30 +00001897
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001898 // If this instruction has a delay slot and .set reorder is active,
1899 // emit a NOP after it.
1900 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
1901 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1902
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001903 if ((Inst.getOpcode() == Mips::JalOneReg ||
1904 Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
1905 isPicAndNotNxxAbi()) {
1906 if (IsCpRestoreSet) {
1907 // We need a NOP between the JALR and the LW:
1908 // If .set reorder has been used, we've already emitted a NOP.
1909 // If .set noreorder has been used, we need to emit a NOP at this point.
1910 if (!AssemblerOptions.back()->isReorder())
1911 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1912
1913 // Load the $gp from the stack.
1914 SmallVector<MCInst, 3> LoadInsts;
1915 createCpRestoreMemOp(true /*IsLoad*/, CpRestoreOffset /*StackOffset*/,
1916 IDLoc, LoadInsts);
1917
1918 for (const MCInst &Inst : LoadInsts)
1919 Instructions.push_back(Inst);
1920
1921 } else
1922 Warning(IDLoc, "no .cprestore used in PIC mode");
1923 }
1924
Jack Carter9e65aa32013-03-22 00:05:30 +00001925 return false;
1926}
1927
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001928MipsAsmParser::MacroExpanderResultTy
1929MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
1930 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001931 switch (Inst.getOpcode()) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001932 default:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001933 return MER_NotAMacro;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001934 case Mips::LoadImm32:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001935 return expandLoadImm(Inst, true, IDLoc, Instructions) ? MER_Fail
1936 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001937 case Mips::LoadImm64:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001938 return expandLoadImm(Inst, false, IDLoc, Instructions) ? MER_Fail
1939 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001940 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001941 case Mips::LoadAddrImm64:
1942 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1943 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
1944 "expected immediate operand kind");
1945
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001946 return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,
1947 Inst.getOperand(1),
1948 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,
1949 Instructions)
1950 ? MER_Fail
1951 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001952 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001953 case Mips::LoadAddrReg64:
1954 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1955 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1956 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
1957 "expected immediate operand kind");
1958
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001959 return expandLoadAddress(Inst.getOperand(0).getReg(),
1960 Inst.getOperand(1).getReg(), Inst.getOperand(2),
1961 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,
1962 Instructions)
1963 ? MER_Fail
1964 : MER_Success;
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001965 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001966 case Mips::B_MMR6_Pseudo:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001967 return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions) ? MER_Fail
1968 : MER_Success;
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001969 case Mips::SWM_MM:
1970 case Mips::LWM_MM:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001971 return expandLoadStoreMultiple(Inst, IDLoc, Instructions) ? MER_Fail
1972 : MER_Success;
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001973 case Mips::JalOneReg:
1974 case Mips::JalTwoReg:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001975 return expandJalWithRegs(Inst, IDLoc, Instructions) ? MER_Fail
1976 : MER_Success;
Toma Tabacue1e460d2015-06-11 10:36:10 +00001977 case Mips::BneImm:
1978 case Mips::BeqImm:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001979 return expandBranchImm(Inst, IDLoc, Instructions) ? MER_Fail : MER_Success;
Toma Tabacu1a108322015-06-17 13:20:24 +00001980 case Mips::BLT:
1981 case Mips::BLE:
1982 case Mips::BGE:
1983 case Mips::BGT:
1984 case Mips::BLTU:
1985 case Mips::BLEU:
1986 case Mips::BGEU:
1987 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00001988 case Mips::BLTL:
1989 case Mips::BLEL:
1990 case Mips::BGEL:
1991 case Mips::BGTL:
1992 case Mips::BLTUL:
1993 case Mips::BLEUL:
1994 case Mips::BGEUL:
1995 case Mips::BGTUL:
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00001996 case Mips::BLTImmMacro:
1997 case Mips::BLEImmMacro:
1998 case Mips::BGEImmMacro:
1999 case Mips::BGTImmMacro:
2000 case Mips::BLTUImmMacro:
2001 case Mips::BLEUImmMacro:
2002 case Mips::BGEUImmMacro:
2003 case Mips::BGTUImmMacro:
2004 case Mips::BLTLImmMacro:
2005 case Mips::BLELImmMacro:
2006 case Mips::BGELImmMacro:
2007 case Mips::BGTLImmMacro:
2008 case Mips::BLTULImmMacro:
2009 case Mips::BLEULImmMacro:
2010 case Mips::BGEULImmMacro:
2011 case Mips::BGTULImmMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002012 return expandCondBranches(Inst, IDLoc, Instructions) ? MER_Fail
2013 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002014 case Mips::SDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002015 return expandDiv(Inst, IDLoc, Instructions, false, true) ? MER_Fail
2016 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002017 case Mips::DSDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002018 return expandDiv(Inst, IDLoc, Instructions, true, true) ? MER_Fail
2019 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002020 case Mips::UDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002021 return expandDiv(Inst, IDLoc, Instructions, false, false) ? MER_Fail
2022 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002023 case Mips::DUDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002024 return expandDiv(Inst, IDLoc, Instructions, true, false) ? MER_Fail
2025 : MER_Success;
Daniel Sanders6394ee52015-10-15 14:52:58 +00002026 case Mips::Ulh:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002027 return expandUlh(Inst, true, IDLoc, Instructions) ? MER_Fail : MER_Success;
Toma Tabacud88d79c2015-06-23 14:39:42 +00002028 case Mips::Ulhu:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002029 return expandUlh(Inst, false, IDLoc, Instructions) ? MER_Fail : MER_Success;
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00002030 case Mips::Ulw:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002031 return expandUlw(Inst, IDLoc, Instructions) ? MER_Fail : MER_Success;
2032 case Mips::NORImm:
2033 return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail
2034 : MER_Success;
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002035 case Mips::ADDi:
2036 case Mips::ADDiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002037 case Mips::SLTi:
2038 case Mips::SLTiu:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002039 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2040 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2041 int64_t ImmValue = Inst.getOperand(2).getImm();
2042 if (isInt<16>(ImmValue))
2043 return MER_NotAMacro;
2044 return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail
2045 : MER_Success;
2046 }
2047 return MER_NotAMacro;
2048 case Mips::ANDi:
2049 case Mips::ORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002050 case Mips::XORi:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002051 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2052 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2053 int64_t ImmValue = Inst.getOperand(2).getImm();
2054 if (isUInt<16>(ImmValue))
2055 return MER_NotAMacro;
2056 return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail
2057 : MER_Success;
2058 }
2059 return MER_NotAMacro;
Jack Carterd0bd6422013-04-18 00:41:53 +00002060 }
Jack Carter30a59822012-10-04 04:03:53 +00002061}
Jack Carter92995f12012-10-06 00:53:28 +00002062
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002063bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
2064 SmallVectorImpl<MCInst> &Instructions) {
2065 // Create a JALR instruction which is going to replace the pseudo-JAL.
2066 MCInst JalrInst;
2067 JalrInst.setLoc(IDLoc);
2068 const MCOperand FirstRegOp = Inst.getOperand(0);
2069 const unsigned Opcode = Inst.getOpcode();
2070
2071 if (Opcode == Mips::JalOneReg) {
2072 // jal $rs => jalr $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002073 if (IsCpRestoreSet && inMicroMipsMode()) {
2074 JalrInst.setOpcode(Mips::JALRS16_MM);
2075 JalrInst.addOperand(FirstRegOp);
2076 } else if (inMicroMipsMode()) {
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002077 JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002078 JalrInst.addOperand(FirstRegOp);
2079 } else {
2080 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002081 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002082 JalrInst.addOperand(FirstRegOp);
2083 }
2084 } else if (Opcode == Mips::JalTwoReg) {
2085 // jal $rd, $rs => jalr $rd, $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002086 if (IsCpRestoreSet && inMicroMipsMode())
2087 JalrInst.setOpcode(Mips::JALRS_MM);
2088 else
2089 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002090 JalrInst.addOperand(FirstRegOp);
2091 const MCOperand SecondRegOp = Inst.getOperand(1);
2092 JalrInst.addOperand(SecondRegOp);
2093 }
2094 Instructions.push_back(JalrInst);
2095
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002096 // If .set reorder is active and branch instruction has a delay slot,
2097 // emit a NOP after it.
2098 const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
2099 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) {
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002100 createNop(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc, Instructions);
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002101 }
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002102
2103 return false;
2104}
2105
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002106/// Can the value be represented by a unsigned N-bit value and a shift left?
Benjamin Kramer039b1042015-10-28 13:54:36 +00002107template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002108 unsigned BitNum = findFirstSet(x);
2109
2110 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2111}
2112
2113/// Load (or add) an immediate into a register.
2114///
2115/// @param ImmValue The immediate to load.
2116/// @param DstReg The register that will hold the immediate.
2117/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2118/// for a simple initialization.
2119/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2120/// @param IsAddress True if the immediate represents an address. False if it
2121/// is an integer.
2122/// @param IDLoc Location of the immediate in the source file.
2123/// @param Instructions The instructions emitted by this expansion.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002124bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002125 unsigned SrcReg, bool Is32BitImm,
2126 bool IsAddress, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00002127 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu00e98672015-05-01 12:19:27 +00002128 if (!Is32BitImm && !isGP64bit()) {
2129 Error(IDLoc, "instruction requires a 64-bit architecture");
2130 return true;
2131 }
2132
Daniel Sanders03f9c012015-07-14 12:24:22 +00002133 if (Is32BitImm) {
2134 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2135 // Sign extend up to 64-bit so that the predicates match the hardware
2136 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2137 // true.
2138 ImmValue = SignExtend64<32>(ImmValue);
2139 } else {
2140 Error(IDLoc, "instruction requires a 32-bit immediate");
2141 return true;
2142 }
2143 }
2144
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002145 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2146 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2147
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002148 bool UseSrcReg = false;
2149 if (SrcReg != Mips::NoRegister)
2150 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002151
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002152 unsigned TmpReg = DstReg;
2153 if (UseSrcReg && (DstReg == SrcReg)) {
2154 // At this point we need AT to perform the expansions and we exit if it is
2155 // not available.
2156 unsigned ATReg = getATReg(IDLoc);
2157 if (!ATReg)
2158 return true;
2159 TmpReg = ATReg;
2160 }
2161
Daniel Sanders03f9c012015-07-14 12:24:22 +00002162 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002163 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002164 SrcReg = ZeroReg;
2165
2166 // This doesn't quite follow the usual ABI expectations for N32 but matches
2167 // traditional assembler behaviour. N32 would normally use addiu for both
2168 // integers and addresses.
2169 if (IsAddress && !Is32BitImm) {
2170 emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
2171 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002172 }
2173
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002174 emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
2175 return false;
2176 }
2177
2178 if (isUInt<16>(ImmValue)) {
2179 unsigned TmpReg = DstReg;
2180 if (SrcReg == DstReg) {
2181 TmpReg = getATReg(IDLoc);
2182 if (!TmpReg)
2183 return true;
2184 }
2185
2186 emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002187 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002188 emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2189 return false;
2190 }
2191
2192 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002193 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002194
Toma Tabacu79588102015-04-29 10:19:56 +00002195 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2196 uint16_t Bits15To0 = ImmValue & 0xffff;
2197
Toma Tabacua3d056f2015-05-15 09:42:11 +00002198 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002199 // Traditional behaviour seems to special case this particular value. It's
2200 // not clear why other masks are handled differently.
2201 if (ImmValue == 0xffffffff) {
Daniel Sandersf1ae3672015-08-18 09:55:57 +00002202 emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, Instructions);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002203 emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, Instructions);
2204 if (UseSrcReg)
2205 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2206 return false;
2207 }
2208
2209 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002210 // upper 32 bits.
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002211 emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002212 emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, Instructions);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002213 if (Bits15To0)
2214 emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
2215 if (UseSrcReg)
2216 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2217 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002218 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002219
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002220 emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, Instructions);
2221 if (Bits15To0)
2222 emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002223 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002224 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2225 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002226 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002227
2228 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2229 if (Is32BitImm) {
2230 Error(IDLoc, "instruction requires a 32-bit immediate");
2231 return true;
2232 }
2233
2234 // Traditionally, these immediates are shifted as little as possible and as
2235 // such we align the most significant bit to bit 15 of our temporary.
2236 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2237 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2238 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2239 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
2240 emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, Instructions);
2241 emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, Instructions);
2242
2243 if (UseSrcReg)
2244 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2245
2246 return false;
2247 }
2248
2249 warnIfNoMacro(IDLoc);
2250
2251 // The remaining case is packed with a sequence of dsll and ori with zeros
2252 // being omitted and any neighbouring dsll's being coalesced.
2253 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2254
2255 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2256 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
2257 IDLoc, Instructions))
2258 return false;
2259
2260 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2261 // skip it and defer the shift to the next chunk.
2262 unsigned ShiftCarriedForwards = 16;
2263 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2264 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2265
2266 if (ImmChunk != 0) {
2267 emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
2268 Instructions);
2269 emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, Instructions);
2270 ShiftCarriedForwards = 0;
2271 }
2272
2273 ShiftCarriedForwards += 16;
2274 }
2275 ShiftCarriedForwards -= 16;
2276
2277 // Finish any remaining shifts left by trailing zeros.
2278 if (ShiftCarriedForwards)
2279 emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
2280 Instructions);
2281
2282 if (UseSrcReg)
2283 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2284
Matheus Almeida3813d572014-06-19 14:39:14 +00002285 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002286}
Jack Carter92995f12012-10-06 00:53:28 +00002287
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002288bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
2289 SmallVectorImpl<MCInst> &Instructions) {
2290 const MCOperand &ImmOp = Inst.getOperand(1);
2291 assert(ImmOp.isImm() && "expected immediate operand kind");
2292 const MCOperand &DstRegOp = Inst.getOperand(0);
2293 assert(DstRegOp.isReg() && "expected register operand kind");
2294
2295 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002296 Is32BitImm, false, IDLoc, Instructions))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002297 return true;
2298
2299 return false;
2300}
2301
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002302bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2303 const MCOperand &Offset,
2304 bool Is32BitAddress, SMLoc IDLoc,
2305 SmallVectorImpl<MCInst> &Instructions) {
2306 // la can't produce a usable address when addresses are 64-bit.
2307 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2308 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2309 // We currently can't do this because we depend on the equality
2310 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2311 Error(IDLoc, "la used to load 64-bit address");
2312 // Continue as if we had 'dla' instead.
2313 Is32BitAddress = false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002314 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002315
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002316 // dla requires 64-bit addresses.
2317 if (!Is32BitAddress && !ABI.ArePtrs64bit()) {
2318 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002319 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002320 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002321
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002322 if (!Offset.isImm())
2323 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
2324 Is32BitAddress, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002325
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002326 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
2327 IDLoc, Instructions);
Jack Carter543fdf82012-10-09 23:29:45 +00002328}
2329
Toma Tabacuf712ede2015-06-17 14:31:51 +00002330bool MipsAsmParser::loadAndAddSymbolAddress(
2331 const MCExpr *SymExpr, unsigned DstReg, unsigned SrcReg, bool Is32BitSym,
2332 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002333 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002334
Daniel Sandersd5a89412015-10-05 13:19:29 +00002335 const MCExpr *Symbol = cast<MCExpr>(SymExpr);
2336 const MipsMCExpr *HiExpr = MipsMCExpr::create(
2337 MCSymbolRefExpr::VK_Mips_ABS_HI, Symbol, getContext());
2338 const MipsMCExpr *LoExpr = MipsMCExpr::create(
2339 MCSymbolRefExpr::VK_Mips_ABS_LO, Symbol, getContext());
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002340
Toma Tabacufb9d1252015-06-22 12:08:39 +00002341 bool UseSrcReg = SrcReg != Mips::NoRegister;
2342
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002343 // This is the 64-bit symbol address expansion.
2344 if (ABI.ArePtrs64bit() && isGP64bit()) {
2345 // We always need AT for the 64-bit expansion.
2346 // If it is not available we exit.
2347 unsigned ATReg = getATReg(IDLoc);
2348 if (!ATReg)
2349 return true;
2350
Daniel Sandersd5a89412015-10-05 13:19:29 +00002351 const MipsMCExpr *HighestExpr = MipsMCExpr::create(
2352 MCSymbolRefExpr::VK_Mips_HIGHEST, Symbol, getContext());
2353 const MipsMCExpr *HigherExpr = MipsMCExpr::create(
2354 MCSymbolRefExpr::VK_Mips_HIGHER, Symbol, getContext());
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002355
2356 if (UseSrcReg && (DstReg == SrcReg)) {
2357 // If $rs is the same as $rd:
2358 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
2359 // daddiu $at, $at, %higher(sym)
2360 // dsll $at, $at, 16
2361 // daddiu $at, $at, %hi(sym)
2362 // dsll $at, $at, 16
2363 // daddiu $at, $at, %lo(sym)
2364 // daddu $rd, $at, $rd
2365 emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
2366 Instructions);
2367 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HigherExpr),
2368 IDLoc, Instructions);
2369 emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
2370 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
2371 Instructions);
2372 emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
2373 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
2374 Instructions);
2375 emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, Instructions);
2376
2377 return false;
2378 }
2379
2380 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2381 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
2382 // lui $at, %hi(sym)
2383 // daddiu $rd, $rd, %higher(sym)
2384 // daddiu $at, $at, %lo(sym)
2385 // dsll32 $rd, $rd, 0
2386 // daddu $rd, $rd, $at
2387 // (daddu $rd, $rd, $rs)
2388 emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
2389 Instructions);
2390 emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
2391 Instructions);
2392 emitRRX(Mips::DADDiu, DstReg, DstReg, MCOperand::createExpr(HigherExpr),
2393 IDLoc, Instructions);
2394 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
2395 Instructions);
2396 emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, Instructions);
2397 emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, Instructions);
2398 if (UseSrcReg)
2399 emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, Instructions);
2400
2401 return false;
2402 }
2403
2404 // And now, the 32-bit symbol address expansion:
2405 // If $rs is the same as $rd:
2406 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
2407 // ori $at, $at, %lo(sym)
2408 // addu $rd, $at, $rd
2409 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2410 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
2411 // ori $rd, $rd, %lo(sym)
2412 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00002413 unsigned TmpReg = DstReg;
2414 if (UseSrcReg && (DstReg == SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002415 // If $rs is the same as $rd, we need to use AT.
2416 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00002417 unsigned ATReg = getATReg(IDLoc);
2418 if (!ATReg)
2419 return true;
2420 TmpReg = ATReg;
2421 }
2422
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002423 emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, Instructions);
2424 emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr), IDLoc,
2425 Instructions);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002426
Toma Tabacufb9d1252015-06-22 12:08:39 +00002427 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002428 emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2429 else
2430 assert(DstReg == TmpReg);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002431
Toma Tabacu674825c2015-06-16 12:16:24 +00002432 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002433}
2434
NAKAMURA Takumi2bbc90c2015-01-23 01:02:07 +00002435bool MipsAsmParser::expandUncondBranchMMPseudo(
2436 MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00002437 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
2438 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002439
2440 MCOperand Offset = Inst.getOperand(0);
2441 if (Offset.isExpr()) {
2442 Inst.clear();
2443 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002444 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2445 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2446 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002447 } else {
2448 assert(Offset.isImm() && "expected immediate operand kind");
Craig Topper55b1f292015-10-10 20:17:07 +00002449 if (isInt<11>(Offset.getImm())) {
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002450 // If offset fits into 11 bits then this instruction becomes microMIPS
2451 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00002452 if (inMicroMipsMode())
2453 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002454 } else {
Craig Topper55b1f292015-10-10 20:17:07 +00002455 if (!isInt<17>(Offset.getImm()))
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002456 Error(IDLoc, "branch target out of range");
2457 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
2458 Error(IDLoc, "branch to misaligned address");
2459 Inst.clear();
2460 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002461 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2462 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2463 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002464 }
2465 }
2466 Instructions.push_back(Inst);
2467
Zoran Jovanovicada70912015-09-07 11:56:37 +00002468 // If .set reorder is active and branch instruction has a delay slot,
2469 // emit a NOP after it.
2470 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
2471 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Toma Tabacu234482a2015-03-16 12:03:39 +00002472 createNop(true, IDLoc, Instructions);
2473
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002474 return false;
2475}
2476
Toma Tabacue1e460d2015-06-11 10:36:10 +00002477bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc,
2478 SmallVectorImpl<MCInst> &Instructions) {
2479 const MCOperand &DstRegOp = Inst.getOperand(0);
2480 assert(DstRegOp.isReg() && "expected register operand kind");
2481
2482 const MCOperand &ImmOp = Inst.getOperand(1);
2483 assert(ImmOp.isImm() && "expected immediate operand kind");
2484
2485 const MCOperand &MemOffsetOp = Inst.getOperand(2);
2486 assert(MemOffsetOp.isImm() && "expected immediate operand kind");
2487
2488 unsigned OpCode = 0;
2489 switch(Inst.getOpcode()) {
2490 case Mips::BneImm:
2491 OpCode = Mips::BNE;
2492 break;
2493 case Mips::BeqImm:
2494 OpCode = Mips::BEQ;
2495 break;
2496 default:
2497 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
2498 break;
2499 }
2500
2501 int64_t ImmValue = ImmOp.getImm();
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002502 if (ImmValue == 0)
2503 emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
2504 Instructions);
2505 else {
Toma Tabacue1e460d2015-06-11 10:36:10 +00002506 warnIfNoMacro(IDLoc);
2507
2508 unsigned ATReg = getATReg(IDLoc);
2509 if (!ATReg)
2510 return true;
2511
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002512 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
2513 IDLoc, Instructions))
Toma Tabacue1e460d2015-06-11 10:36:10 +00002514 return true;
2515
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002516 emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, Instructions);
Toma Tabacue1e460d2015-06-11 10:36:10 +00002517 }
2518 return false;
2519}
2520
Jack Carter9e65aa32013-03-22 00:05:30 +00002521void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00002522 SmallVectorImpl<MCInst> &Instructions,
2523 bool isLoad, bool isImmOpnd) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002524 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00002525 const MCExpr *ExprOffset;
2526 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00002527 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002528 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2529 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002530 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002531 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2532 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002533 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00002534 if (isImmOpnd) {
2535 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
2536 ImmOffset = Inst.getOperand(2).getImm();
2537 LoOffset = ImmOffset & 0x0000ffff;
2538 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00002539 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00002540 if (LoOffset & 0x8000)
2541 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00002542 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00002543 ExprOffset = Inst.getOperand(2).getExpr();
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002544 // These are some of the types of expansions we perform here:
2545 // 1) lw $8, sym => lui $8, %hi(sym)
2546 // lw $8, %lo(sym)($8)
2547 // 2) lw $8, offset($9) => lui $8, %hi(offset)
2548 // add $8, $8, $9
2549 // lw $8, %lo(offset)($9)
2550 // 3) lw $8, offset($8) => lui $at, %hi(offset)
2551 // add $at, $at, $8
2552 // lw $8, %lo(offset)($at)
2553 // 4) sw $8, sym => lui $at, %hi(sym)
2554 // sw $8, %lo(sym)($at)
2555 // 5) sw $8, offset($8) => lui $at, %hi(offset)
2556 // add $at, $at, $8
2557 // sw $8, %lo(offset)($at)
2558 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
2559 // ldc1 $f0, %lo(sym)($at)
2560 //
2561 // For load instructions we can use the destination register as a temporary
2562 // if base and dst are different (examples 1 and 2) and if the base register
2563 // is general purpose otherwise we must use $at (example 6) and error if it's
2564 // not available. For stores we must use $at (examples 4 and 5) because we
2565 // must not clobber the source register setting up the offset.
2566 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
2567 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
2568 unsigned RegClassIDOp0 =
2569 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
2570 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
2571 (RegClassIDOp0 == Mips::GPR64RegClassID);
2572 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00002573 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002574 else {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002575 // At this point we need AT to perform the expansions and we exit if it is
2576 // not available.
Toma Tabacu89a712b2015-04-15 10:48:56 +00002577 TmpRegNum = getATReg(IDLoc);
2578 if (!TmpRegNum)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002579 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002580 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002581
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002582 emitRX(Mips::LUi, TmpRegNum,
2583 isImmOpnd ? MCOperand::createImm(HiOffset)
2584 : MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "hi")),
2585 IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00002586 // Add temp register to base.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002587 if (BaseRegNum != Mips::ZERO)
2588 emitRRR(Mips::ADDu, TmpRegNum, TmpRegNum, BaseRegNum, IDLoc, Instructions);
Alp Tokercb402912014-01-24 17:20:08 +00002589 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00002590 // of offset and new base.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002591 emitRRX(Inst.getOpcode(), RegOpNum, TmpRegNum,
2592 isImmOpnd
2593 ? MCOperand::createImm(LoOffset)
2594 : MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "lo")),
2595 IDLoc, Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +00002596}
2597
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002598bool
2599MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2600 SmallVectorImpl<MCInst> &Instructions) {
2601 unsigned OpNum = Inst.getNumOperands();
2602 unsigned Opcode = Inst.getOpcode();
2603 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2604
2605 assert (Inst.getOperand(OpNum - 1).isImm() &&
2606 Inst.getOperand(OpNum - 2).isReg() &&
2607 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2608
2609 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2610 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
2611 Inst.getOperand(OpNum - 2).getReg() == Mips::SP &&
2612 Inst.getOperand(OpNum - 3).getReg() == Mips::RA)
2613 // It can be implemented as SWM16 or LWM16 instruction.
2614 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2615
2616 Inst.setOpcode(NewOpcode);
2617 Instructions.push_back(Inst);
2618 return false;
2619}
2620
Toma Tabacu1a108322015-06-17 13:20:24 +00002621bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
2622 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002623 bool EmittedNoMacroWarning = false;
Toma Tabacu1a108322015-06-17 13:20:24 +00002624 unsigned PseudoOpcode = Inst.getOpcode();
2625 unsigned SrcReg = Inst.getOperand(0).getReg();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002626 const MCOperand &TrgOp = Inst.getOperand(1);
Toma Tabacu1a108322015-06-17 13:20:24 +00002627 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
2628
2629 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002630 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00002631
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002632 unsigned TrgReg;
2633 if (TrgOp.isReg())
2634 TrgReg = TrgOp.getReg();
2635 else if (TrgOp.isImm()) {
2636 warnIfNoMacro(IDLoc);
2637 EmittedNoMacroWarning = true;
2638
2639 TrgReg = getATReg(IDLoc);
2640 if (!TrgReg)
2641 return true;
2642
2643 switch(PseudoOpcode) {
2644 default:
2645 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2646 case Mips::BLTImmMacro:
2647 PseudoOpcode = Mips::BLT;
2648 break;
2649 case Mips::BLEImmMacro:
2650 PseudoOpcode = Mips::BLE;
2651 break;
2652 case Mips::BGEImmMacro:
2653 PseudoOpcode = Mips::BGE;
2654 break;
2655 case Mips::BGTImmMacro:
2656 PseudoOpcode = Mips::BGT;
2657 break;
2658 case Mips::BLTUImmMacro:
2659 PseudoOpcode = Mips::BLTU;
2660 break;
2661 case Mips::BLEUImmMacro:
2662 PseudoOpcode = Mips::BLEU;
2663 break;
2664 case Mips::BGEUImmMacro:
2665 PseudoOpcode = Mips::BGEU;
2666 break;
2667 case Mips::BGTUImmMacro:
2668 PseudoOpcode = Mips::BGTU;
2669 break;
2670 case Mips::BLTLImmMacro:
2671 PseudoOpcode = Mips::BLTL;
2672 break;
2673 case Mips::BLELImmMacro:
2674 PseudoOpcode = Mips::BLEL;
2675 break;
2676 case Mips::BGELImmMacro:
2677 PseudoOpcode = Mips::BGEL;
2678 break;
2679 case Mips::BGTLImmMacro:
2680 PseudoOpcode = Mips::BGTL;
2681 break;
2682 case Mips::BLTULImmMacro:
2683 PseudoOpcode = Mips::BLTUL;
2684 break;
2685 case Mips::BLEULImmMacro:
2686 PseudoOpcode = Mips::BLEUL;
2687 break;
2688 case Mips::BGEULImmMacro:
2689 PseudoOpcode = Mips::BGEUL;
2690 break;
2691 case Mips::BGTULImmMacro:
2692 PseudoOpcode = Mips::BGTUL;
2693 break;
2694 }
2695
2696 if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
2697 false, IDLoc, Instructions))
2698 return true;
2699 }
2700
Toma Tabacu1a108322015-06-17 13:20:24 +00002701 switch (PseudoOpcode) {
2702 case Mips::BLT:
2703 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002704 case Mips::BLTL:
2705 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002706 AcceptsEquality = false;
2707 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002708 IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
2709 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002710 ZeroSrcOpcode = Mips::BGTZ;
2711 ZeroTrgOpcode = Mips::BLTZ;
2712 break;
2713 case Mips::BLE:
2714 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002715 case Mips::BLEL:
2716 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002717 AcceptsEquality = true;
2718 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002719 IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
2720 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002721 ZeroSrcOpcode = Mips::BGEZ;
2722 ZeroTrgOpcode = Mips::BLEZ;
2723 break;
2724 case Mips::BGE:
2725 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002726 case Mips::BGEL:
2727 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002728 AcceptsEquality = true;
2729 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002730 IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
2731 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002732 ZeroSrcOpcode = Mips::BLEZ;
2733 ZeroTrgOpcode = Mips::BGEZ;
2734 break;
2735 case Mips::BGT:
2736 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002737 case Mips::BGTL:
2738 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002739 AcceptsEquality = false;
2740 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002741 IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
2742 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002743 ZeroSrcOpcode = Mips::BLTZ;
2744 ZeroTrgOpcode = Mips::BGTZ;
2745 break;
2746 default:
2747 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2748 }
2749
Toma Tabacu1a108322015-06-17 13:20:24 +00002750 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
2751 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
2752 if (IsSrcRegZero && IsTrgRegZero) {
2753 // FIXME: All of these Opcode-specific if's are needed for compatibility
2754 // with GAS' behaviour. However, they may not generate the most efficient
2755 // code in some circumstances.
2756 if (PseudoOpcode == Mips::BLT) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002757 emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2758 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002759 return false;
2760 }
2761 if (PseudoOpcode == Mips::BLE) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002762 emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2763 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002764 Warning(IDLoc, "branch is always taken");
2765 return false;
2766 }
2767 if (PseudoOpcode == Mips::BGE) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002768 emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2769 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002770 Warning(IDLoc, "branch is always taken");
2771 return false;
2772 }
2773 if (PseudoOpcode == Mips::BGT) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002774 emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2775 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002776 return false;
2777 }
2778 if (PseudoOpcode == Mips::BGTU) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002779 emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
2780 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002781 return false;
2782 }
2783 if (AcceptsEquality) {
2784 // If both registers are $0 and the pseudo-branch accepts equality, it
2785 // will always be taken, so we emit an unconditional branch.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002786 emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
2787 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002788 Warning(IDLoc, "branch is always taken");
2789 return false;
2790 }
2791 // If both registers are $0 and the pseudo-branch does not accept
2792 // equality, it will never be taken, so we don't have to emit anything.
2793 return false;
2794 }
2795 if (IsSrcRegZero || IsTrgRegZero) {
2796 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
2797 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
2798 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
2799 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
2800 // the pseudo-branch will never be taken, so we don't emit anything.
2801 // This only applies to unsigned pseudo-branches.
2802 return false;
2803 }
2804 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
2805 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
2806 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
2807 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
2808 // the pseudo-branch will always be taken, so we emit an unconditional
2809 // branch.
2810 // This only applies to unsigned pseudo-branches.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002811 emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
2812 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002813 Warning(IDLoc, "branch is always taken");
2814 return false;
2815 }
2816 if (IsUnsigned) {
2817 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
2818 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
2819 // the pseudo-branch will be taken only when the non-zero register is
2820 // different from 0, so we emit a BNEZ.
2821 //
2822 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
2823 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
2824 // the pseudo-branch will be taken only when the non-zero register is
2825 // equal to 0, so we emit a BEQZ.
2826 //
2827 // Because only BLEU and BGEU branch on equality, we can use the
2828 // AcceptsEquality variable to decide when to emit the BEQZ.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002829 emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
2830 IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
2831 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002832 return false;
2833 }
2834 // If we have a signed pseudo-branch and one of the registers is $0,
2835 // we can use an appropriate compare-to-zero branch. We select which one
2836 // to use in the switch statement above.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002837 emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
2838 IsSrcRegZero ? TrgReg : SrcReg, MCOperand::createExpr(OffsetExpr),
2839 IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002840 return false;
2841 }
2842
2843 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
2844 // expansions. If it is not available, we return.
2845 unsigned ATRegNum = getATReg(IDLoc);
2846 if (!ATRegNum)
2847 return true;
2848
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002849 if (!EmittedNoMacroWarning)
2850 warnIfNoMacro(IDLoc);
Toma Tabacu1a108322015-06-17 13:20:24 +00002851
2852 // SLT fits well with 2 of our 4 pseudo-branches:
2853 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
2854 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
2855 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
2856 // This is accomplished by using a BNEZ with the result of the SLT.
2857 //
2858 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
2859 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
2860 // Because only BGE and BLE branch on equality, we can use the
2861 // AcceptsEquality variable to decide when to emit the BEQZ.
2862 // Note that the order of the SLT arguments doesn't change between
2863 // opposites.
2864 //
2865 // The same applies to the unsigned variants, except that SLTu is used
2866 // instead of SLT.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002867 emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
2868 ReverseOrderSLT ? TrgReg : SrcReg, ReverseOrderSLT ? SrcReg : TrgReg,
2869 IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002870
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002871 emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
2872 : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
2873 ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2874 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002875 return false;
2876}
2877
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002878bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc,
2879 SmallVectorImpl<MCInst> &Instructions,
2880 const bool IsMips64, const bool Signed) {
2881 if (hasMips32r6()) {
2882 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
2883 return false;
2884 }
2885
2886 warnIfNoMacro(IDLoc);
2887
2888 const MCOperand &RsRegOp = Inst.getOperand(0);
2889 assert(RsRegOp.isReg() && "expected register operand kind");
2890 unsigned RsReg = RsRegOp.getReg();
2891
2892 const MCOperand &RtRegOp = Inst.getOperand(1);
2893 assert(RtRegOp.isReg() && "expected register operand kind");
2894 unsigned RtReg = RtRegOp.getReg();
2895 unsigned DivOp;
2896 unsigned ZeroReg;
2897
2898 if (IsMips64) {
2899 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
2900 ZeroReg = Mips::ZERO_64;
2901 } else {
2902 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
2903 ZeroReg = Mips::ZERO;
2904 }
2905
2906 bool UseTraps = useTraps();
2907
2908 if (RsReg == Mips::ZERO || RsReg == Mips::ZERO_64) {
2909 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)
2910 Warning(IDLoc, "dividing zero by zero");
2911 if (IsMips64) {
2912 if (Signed && (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)) {
2913 if (UseTraps) {
2914 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2915 return false;
2916 }
2917
2918 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2919 return false;
2920 }
2921 } else {
2922 emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
2923 return false;
2924 }
2925 }
2926
2927 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
2928 Warning(IDLoc, "division by zero");
2929 if (Signed) {
2930 if (UseTraps) {
2931 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2932 return false;
2933 }
2934
2935 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2936 return false;
2937 }
2938 }
2939
2940 // FIXME: The values for these two BranchTarget variables may be different in
2941 // micromips. These magic numbers need to be removed.
2942 unsigned BranchTargetNoTraps;
2943 unsigned BranchTarget;
2944
2945 if (UseTraps) {
2946 BranchTarget = IsMips64 ? 12 : 8;
2947 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2948 } else {
2949 BranchTarget = IsMips64 ? 20 : 16;
2950 BranchTargetNoTraps = 8;
2951 // Branch to the li instruction.
2952 emitRRI(Mips::BNE, RtReg, ZeroReg, BranchTargetNoTraps, IDLoc,
2953 Instructions);
2954 }
2955
2956 emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
2957
2958 if (!UseTraps)
2959 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2960
2961 if (!Signed) {
2962 emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
2963 return false;
2964 }
2965
2966 unsigned ATReg = getATReg(IDLoc);
2967 if (!ATReg)
2968 return true;
2969
2970 emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, Instructions);
2971 if (IsMips64) {
2972 // Branch to the mflo instruction.
2973 emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
2974 emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, Instructions);
2975 emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, Instructions);
2976 } else {
2977 // Branch to the mflo instruction.
2978 emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
2979 emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, Instructions);
2980 }
2981
2982 if (UseTraps)
2983 emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, Instructions);
2984 else {
2985 // Branch to the mflo instruction.
2986 emitRRI(Mips::BNE, RsReg, ATReg, BranchTargetNoTraps, IDLoc, Instructions);
2987 emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, Instructions);
2988 emitII(Mips::BREAK, 0x6, 0, IDLoc, Instructions);
2989 }
2990 emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
2991 return false;
2992}
2993
Daniel Sanders6394ee52015-10-15 14:52:58 +00002994bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
2995 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacud88d79c2015-06-23 14:39:42 +00002996 if (hasMips32r6() || hasMips64r6()) {
2997 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
2998 return false;
2999 }
3000
3001 warnIfNoMacro(IDLoc);
3002
3003 const MCOperand &DstRegOp = Inst.getOperand(0);
3004 assert(DstRegOp.isReg() && "expected register operand kind");
3005
3006 const MCOperand &SrcRegOp = Inst.getOperand(1);
3007 assert(SrcRegOp.isReg() && "expected register operand kind");
3008
3009 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3010 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3011
3012 unsigned DstReg = DstRegOp.getReg();
3013 unsigned SrcReg = SrcRegOp.getReg();
3014 int64_t OffsetValue = OffsetImmOp.getImm();
3015
3016 // NOTE: We always need AT for ULHU, as it is always used as the source
3017 // register for one of the LBu's.
3018 unsigned ATReg = getATReg(IDLoc);
3019 if (!ATReg)
3020 return true;
3021
3022 // When the value of offset+1 does not fit in 16 bits, we have to load the
3023 // offset in AT, (D)ADDu the original source register (if there was one), and
3024 // then use AT as the source register for the 2 generated LBu's.
3025 bool LoadedOffsetInAT = false;
3026 if (!isInt<16>(OffsetValue + 1) || !isInt<16>(OffsetValue)) {
3027 LoadedOffsetInAT = true;
3028
3029 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003030 true, IDLoc, Instructions))
Toma Tabacud88d79c2015-06-23 14:39:42 +00003031 return true;
3032
3033 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3034 // because it will make our output more similar to GAS'. For example,
3035 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3036 // instead of just an "ori $1, $9, 32768".
3037 // NOTE: If there is no source register specified in the ULHU, the parser
3038 // will interpret it as $0.
3039 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
3040 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
3041 }
3042
3043 unsigned FirstLbuDstReg = LoadedOffsetInAT ? DstReg : ATReg;
3044 unsigned SecondLbuDstReg = LoadedOffsetInAT ? ATReg : DstReg;
3045 unsigned LbuSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3046
3047 int64_t FirstLbuOffset = 0, SecondLbuOffset = 0;
3048 if (isLittle()) {
3049 FirstLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3050 SecondLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3051 } else {
3052 FirstLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3053 SecondLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3054 }
3055
3056 unsigned SllReg = LoadedOffsetInAT ? DstReg : ATReg;
3057
Daniel Sanders6394ee52015-10-15 14:52:58 +00003058 emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
3059 FirstLbuOffset, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003060
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003061 emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondLbuOffset, IDLoc,
3062 Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003063
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003064 emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003065
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003066 emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003067
3068 return false;
3069}
3070
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003071bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc,
3072 SmallVectorImpl<MCInst> &Instructions) {
3073 if (hasMips32r6() || hasMips64r6()) {
3074 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3075 return false;
3076 }
3077
3078 const MCOperand &DstRegOp = Inst.getOperand(0);
3079 assert(DstRegOp.isReg() && "expected register operand kind");
3080
3081 const MCOperand &SrcRegOp = Inst.getOperand(1);
3082 assert(SrcRegOp.isReg() && "expected register operand kind");
3083
3084 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3085 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3086
3087 unsigned SrcReg = SrcRegOp.getReg();
3088 int64_t OffsetValue = OffsetImmOp.getImm();
3089 unsigned ATReg = 0;
3090
3091 // When the value of offset+3 does not fit in 16 bits, we have to load the
3092 // offset in AT, (D)ADDu the original source register (if there was one), and
3093 // then use AT as the source register for the generated LWL and LWR.
3094 bool LoadedOffsetInAT = false;
3095 if (!isInt<16>(OffsetValue + 3) || !isInt<16>(OffsetValue)) {
3096 ATReg = getATReg(IDLoc);
3097 if (!ATReg)
3098 return true;
3099 LoadedOffsetInAT = true;
3100
3101 warnIfNoMacro(IDLoc);
3102
3103 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003104 true, IDLoc, Instructions))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003105 return true;
3106
3107 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3108 // because it will make our output more similar to GAS'. For example,
3109 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3110 // instead of just an "ori $1, $9, 32768".
3111 // NOTE: If there is no source register specified in the ULW, the parser
3112 // will interpret it as $0.
3113 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
3114 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
3115 }
3116
3117 unsigned FinalSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3118 int64_t LeftLoadOffset = 0, RightLoadOffset = 0;
3119 if (isLittle()) {
3120 LeftLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3121 RightLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3122 } else {
3123 LeftLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3124 RightLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3125 }
3126
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003127 emitRRI(Mips::LWL, DstRegOp.getReg(), FinalSrcReg, LeftLoadOffset, IDLoc,
3128 Instructions);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003129
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003130 emitRRI(Mips::LWR, DstRegOp.getReg(), FinalSrcReg, RightLoadOffset, IDLoc,
3131 Instructions);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003132
3133 return false;
3134}
3135
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003136bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
3137 SmallVectorImpl<MCInst> &Instructions) {
3138
3139 assert (Inst.getNumOperands() == 3 && "Invalid operand count");
3140 assert (Inst.getOperand(0).isReg() &&
3141 Inst.getOperand(1).isReg() &&
3142 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
3143
3144 unsigned ATReg = Mips::NoRegister;
3145 unsigned FinalDstReg = Mips::NoRegister;
3146 unsigned DstReg = Inst.getOperand(0).getReg();
3147 unsigned SrcReg = Inst.getOperand(1).getReg();
3148 int64_t ImmValue = Inst.getOperand(2).getImm();
3149
3150 bool Is32Bit = isInt<32>(ImmValue) || isUInt<32>(ImmValue);
3151
3152 unsigned FinalOpcode = Inst.getOpcode();
3153
3154 if (DstReg == SrcReg) {
3155 ATReg = getATReg(Inst.getLoc());
3156 if (!ATReg)
3157 return true;
3158 FinalDstReg = DstReg;
3159 DstReg = ATReg;
3160 }
3161
3162 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Instructions)) {
3163 switch (FinalOpcode) {
3164 default:
3165 llvm_unreachable("unimplemented expansion");
3166 case (Mips::ADDi):
3167 FinalOpcode = Mips::ADD;
3168 break;
3169 case (Mips::ADDiu):
3170 FinalOpcode = Mips::ADDu;
3171 break;
3172 case (Mips::ANDi):
3173 FinalOpcode = Mips::AND;
3174 break;
3175 case (Mips::NORImm):
3176 FinalOpcode = Mips::NOR;
3177 break;
3178 case (Mips::ORi):
3179 FinalOpcode = Mips::OR;
3180 break;
3181 case (Mips::SLTi):
3182 FinalOpcode = Mips::SLT;
3183 break;
3184 case (Mips::SLTiu):
3185 FinalOpcode = Mips::SLTu;
3186 break;
3187 case (Mips::XORi):
3188 FinalOpcode = Mips::XOR;
3189 break;
3190 }
3191
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003192 if (FinalDstReg == Mips::NoRegister)
3193 emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, Instructions);
3194 else
3195 emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc,
3196 Instructions);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003197 return false;
3198 }
3199 return true;
3200}
3201
Toma Tabacu234482a2015-03-16 12:03:39 +00003202void MipsAsmParser::createNop(bool hasShortDelaySlot, SMLoc IDLoc,
3203 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003204 if (hasShortDelaySlot)
3205 emitRR(Mips::MOVE16_MM, Mips::ZERO, Mips::ZERO, IDLoc, Instructions);
3206 else
3207 emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, Instructions);
Toma Tabacu234482a2015-03-16 12:03:39 +00003208}
3209
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003210void MipsAsmParser::createAddu(unsigned DstReg, unsigned SrcReg,
Toma Tabacu0b3e9782015-06-23 14:00:54 +00003211 unsigned TrgReg, bool Is64Bit,
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003212 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanders03f9c012015-07-14 12:24:22 +00003213 emitRRR(Is64Bit ? Mips::DADDu : Mips::ADDu, DstReg, SrcReg, TrgReg, SMLoc(),
3214 Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003215}
3216
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003217void MipsAsmParser::createCpRestoreMemOp(
3218 bool IsLoad, int StackOffset, SMLoc IDLoc,
3219 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003220 // If the offset can not fit into 16 bits, we need to expand.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003221 if (!isInt<16>(StackOffset)) {
3222 MCInst MemInst;
3223 MemInst.setOpcode(IsLoad ? Mips::LW : Mips::SW);
3224 MemInst.addOperand(MCOperand::createReg(Mips::GP));
3225 MemInst.addOperand(MCOperand::createReg(Mips::SP));
3226 MemInst.addOperand(MCOperand::createImm(StackOffset));
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003227 expandMemInst(MemInst, IDLoc, Instructions, IsLoad, true /*HasImmOpnd*/);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003228 return;
3229 }
3230
3231 emitRRI(IsLoad ? Mips::LW : Mips::SW, Mips::GP, Mips::SP, StackOffset, IDLoc,
3232 Instructions);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003233}
3234
Matheus Almeida595fcab2014-06-11 15:05:56 +00003235unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
3236 // As described by the Mips32r2 spec, the registers Rd and Rs for
3237 // jalr.hb must be different.
3238 unsigned Opcode = Inst.getOpcode();
3239
3240 if (Opcode == Mips::JALR_HB &&
3241 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
3242 return Match_RequiresDifferentSrcAndDst;
3243
3244 return Match_Success;
3245}
3246
Daniel Sanders52da7af2015-11-06 12:11:03 +00003247static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
3248 uint64_t ErrorInfo) {
3249 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
3250 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
3251 if (ErrorLoc == SMLoc())
3252 return Loc;
3253 return ErrorLoc;
3254 }
3255 return Loc;
3256}
3257
David Blaikie960ea3f2014-06-08 16:18:35 +00003258bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3259 OperandVector &Operands,
3260 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003261 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00003262 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00003263
Jack Carterb4dbc172012-09-05 23:34:03 +00003264 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00003265 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00003266 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003267 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00003268
3269 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003270 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003271 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00003272 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00003273 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00003274 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00003275 return false;
3276 }
3277 case Match_MissingFeature:
3278 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
3279 return true;
3280 case Match_InvalidOperand: {
3281 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00003282 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003283 if (ErrorInfo >= Operands.size())
3284 return Error(IDLoc, "too few operands for instruction");
3285
Daniel Sanders52da7af2015-11-06 12:11:03 +00003286 ErrorLoc = Operands[ErrorInfo]->getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00003287 if (ErrorLoc == SMLoc())
3288 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00003289 }
3290
3291 return Error(ErrorLoc, "invalid operand for instruction");
3292 }
3293 case Match_MnemonicFail:
3294 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00003295 case Match_RequiresDifferentSrcAndDst:
3296 return Error(IDLoc, "source and destination must be different");
Daniel Sanders52da7af2015-11-06 12:11:03 +00003297 case Match_Immz:
3298 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
Jack Carterb4dbc172012-09-05 23:34:03 +00003299 }
Craig Topper589ceee2015-01-03 08:16:34 +00003300
3301 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00003302}
3303
Toma Tabacud9d344b2015-04-27 14:05:04 +00003304void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
3305 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
3306 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
3307 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003308}
3309
Toma Tabacu81496c12015-05-20 08:54:45 +00003310void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
3311 if (!AssemblerOptions.back()->isMacro())
3312 Warning(Loc, "macro instruction expanded into multiple instructions");
3313}
3314
Daniel Sandersef638fe2014-10-03 15:37:37 +00003315void
3316MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
3317 SMRange Range, bool ShowColors) {
3318 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00003319 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00003320 ShowColors);
3321}
3322
Jack Carter1ac53222013-02-20 23:11:17 +00003323int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003324 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003325
Vladimir Medic4c299852013-11-06 11:27:05 +00003326 CC = StringSwitch<unsigned>(Name)
3327 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003328 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00003329 .Case("a0", 4)
3330 .Case("a1", 5)
3331 .Case("a2", 6)
3332 .Case("a3", 7)
3333 .Case("v0", 2)
3334 .Case("v1", 3)
3335 .Case("s0", 16)
3336 .Case("s1", 17)
3337 .Case("s2", 18)
3338 .Case("s3", 19)
3339 .Case("s4", 20)
3340 .Case("s5", 21)
3341 .Case("s6", 22)
3342 .Case("s7", 23)
3343 .Case("k0", 26)
3344 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003345 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00003346 .Case("sp", 29)
3347 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003348 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00003349 .Case("ra", 31)
3350 .Case("t0", 8)
3351 .Case("t1", 9)
3352 .Case("t2", 10)
3353 .Case("t3", 11)
3354 .Case("t4", 12)
3355 .Case("t5", 13)
3356 .Case("t6", 14)
3357 .Case("t7", 15)
3358 .Case("t8", 24)
3359 .Case("t9", 25)
3360 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003361
Toma Tabacufda445c2014-09-15 15:33:01 +00003362 if (!(isABI_N32() || isABI_N64()))
3363 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003364
Daniel Sandersef638fe2014-10-03 15:37:37 +00003365 if (12 <= CC && CC <= 15) {
3366 // Name is one of t4-t7
3367 AsmToken RegTok = getLexer().peekTok();
3368 SMRange RegRange = RegTok.getLocRange();
3369
3370 StringRef FixedName = StringSwitch<StringRef>(Name)
3371 .Case("t4", "t0")
3372 .Case("t5", "t1")
3373 .Case("t6", "t2")
3374 .Case("t7", "t3")
3375 .Default("");
3376 assert(FixedName != "" && "Register name is not one of t4-t7.");
3377
3378 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
3379 "Did you mean $" + FixedName + "?", RegRange);
3380 }
3381
Toma Tabacufda445c2014-09-15 15:33:01 +00003382 // Although SGI documentation just cuts out t0-t3 for n32/n64,
3383 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
3384 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
3385 if (8 <= CC && CC <= 11)
3386 CC += 4;
3387
3388 if (CC == -1)
3389 CC = StringSwitch<unsigned>(Name)
3390 .Case("a4", 8)
3391 .Case("a5", 9)
3392 .Case("a6", 10)
3393 .Case("a7", 11)
3394 .Case("kt0", 26)
3395 .Case("kt1", 27)
3396 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003397
3398 return CC;
3399}
Jack Carterd0bd6422013-04-18 00:41:53 +00003400
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003401int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
3402 int CC;
3403
3404 CC = StringSwitch<unsigned>(Name)
3405 .Case("hwr_cpunum", 0)
3406 .Case("hwr_synci_step", 1)
3407 .Case("hwr_cc", 2)
3408 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00003409 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003410 .Default(-1);
3411
3412 return CC;
3413}
3414
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003415int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003416
Jack Cartera63b16a2012-09-07 00:23:42 +00003417 if (Name[0] == 'f') {
3418 StringRef NumString = Name.substr(1);
3419 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003420 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003421 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003422 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00003423 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003424 return IntVal;
3425 }
3426 return -1;
3427}
Jack Cartera63b16a2012-09-07 00:23:42 +00003428
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003429int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
3430
3431 if (Name.startswith("fcc")) {
3432 StringRef NumString = Name.substr(3);
3433 unsigned IntVal;
3434 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003435 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003436 if (IntVal > 7) // There are only 8 fcc registers.
3437 return -1;
3438 return IntVal;
3439 }
3440 return -1;
3441}
3442
3443int MipsAsmParser::matchACRegisterName(StringRef Name) {
3444
Akira Hatanaka274d24c2013-08-14 01:15:52 +00003445 if (Name.startswith("ac")) {
3446 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003447 unsigned IntVal;
3448 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003449 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003450 if (IntVal > 3) // There are only 3 acc registers.
3451 return -1;
3452 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00003453 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003454 return -1;
3455}
Jack Carterd0bd6422013-04-18 00:41:53 +00003456
Jack Carter5dc8ac92013-09-25 23:50:44 +00003457int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
3458 unsigned IntVal;
3459
3460 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
3461 return -1;
3462
3463 if (IntVal > 31)
3464 return -1;
3465
3466 return IntVal;
3467}
3468
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003469int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
3470 int CC;
3471
3472 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00003473 .Case("msair", 0)
3474 .Case("msacsr", 1)
3475 .Case("msaaccess", 2)
3476 .Case("msasave", 3)
3477 .Case("msamodify", 4)
3478 .Case("msarequest", 5)
3479 .Case("msamap", 6)
3480 .Case("msaunmap", 7)
3481 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003482
3483 return CC;
3484}
3485
Toma Tabacu89a712b2015-04-15 10:48:56 +00003486unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00003487 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00003488 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00003489 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00003490 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00003491 return 0;
3492 }
3493 unsigned AT = getReg(
3494 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00003495 return AT;
3496}
Jack Carter0b744b32012-10-04 02:29:46 +00003497
Jack Carterd0bd6422013-04-18 00:41:53 +00003498unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00003499 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00003500}
3501
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003502unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003503 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00003504 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003505}
3506
Jack Carter873c7242013-01-12 01:03:14 +00003507int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003508 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00003509 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00003510 return -1;
3511
Jack Carter873c7242013-01-12 01:03:14 +00003512 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00003513}
3514
Toma Tabacu13964452014-09-04 13:23:44 +00003515bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003516 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00003517 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003518
Jack Carter30a59822012-10-04 04:03:53 +00003519 // Check if the current operand has a custom associated parser, if so, try to
3520 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00003521 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3522 if (ResTy == MatchOperand_Success)
3523 return false;
3524 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3525 // there was a match, but an error occurred, in which case, just return that
3526 // the operand parsing failed.
3527 if (ResTy == MatchOperand_ParseFail)
3528 return true;
3529
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003530 DEBUG(dbgs() << ".. Generic Parser\n");
3531
Jack Carterb4dbc172012-09-05 23:34:03 +00003532 switch (getLexer().getKind()) {
3533 default:
3534 Error(Parser.getTok().getLoc(), "unexpected token in operand");
3535 return true;
3536 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003537 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00003538 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00003539
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003540 // Almost all registers have been parsed by custom parsers. There is only
3541 // one exception to this. $zero (and it's alias $0) will reach this point
3542 // for div, divu, and similar instructions because it is not an operand
3543 // to the instruction definition but an explicit register. Special case
3544 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00003545 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00003546 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003547
Jack Carterd0bd6422013-04-18 00:41:53 +00003548 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00003549 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003550 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00003551 return true;
3552
Jack Carter873c7242013-01-12 01:03:14 +00003553 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00003554 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00003555 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00003556 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003557 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00003558
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003559 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003560 return false;
3561 }
Vladimir Medic4c299852013-11-06 11:27:05 +00003562 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00003563 case AsmToken::LParen:
3564 case AsmToken::Minus:
3565 case AsmToken::Plus:
3566 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00003567 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00003568 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003569 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00003570 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003571 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00003572 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00003573 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003574 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003575 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003576 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00003577 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00003578 return true;
3579
Jack Carter873c7242013-01-12 01:03:14 +00003580 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3581
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003582 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00003583 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003584 } // case AsmToken::Percent
3585 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00003586 return true;
3587}
3588
Vladimir Medic4c299852013-11-06 11:27:05 +00003589const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00003590 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00003591 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00003592 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00003593 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00003594 // It's a constant, evaluate reloc value.
3595 int16_t Val;
3596 switch (getVariantKind(RelocStr)) {
3597 case MCSymbolRefExpr::VK_Mips_ABS_LO:
3598 // Get the 1st 16-bits.
3599 Val = MCE->getValue() & 0xffff;
3600 break;
3601 case MCSymbolRefExpr::VK_Mips_ABS_HI:
3602 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
3603 // 16 bits being negative.
3604 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
3605 break;
3606 case MCSymbolRefExpr::VK_Mips_HIGHER:
3607 // Get the 3rd 16-bits.
3608 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
3609 break;
3610 case MCSymbolRefExpr::VK_Mips_HIGHEST:
3611 // Get the 4th 16-bits.
3612 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
3613 break;
3614 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00003615 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00003616 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00003617 return MCConstantExpr::create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00003618 }
3619
Jack Carterb5cf5902013-04-17 00:18:04 +00003620 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003621 // It's a symbol, create a symbolic expression from the symbol.
Toma Tabacu07c97b32015-06-17 10:43:45 +00003622 const MCSymbol *Symbol = &MSRE->getSymbol();
Jack Carterb5cf5902013-04-17 00:18:04 +00003623 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003624 Res = MCSymbolRefExpr::create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003625 return Res;
3626 }
3627
3628 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00003629 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
3630
Sasa Stankovic06c47802014-04-03 10:37:45 +00003631 // Try to create target expression.
3632 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
Jim Grosbach13760bd2015-05-30 01:25:56 +00003633 return MipsMCExpr::create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00003634
Jack Carterd0bd6422013-04-18 00:41:53 +00003635 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
3636 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003637 Res = MCBinaryExpr::create(BE->getOpcode(), LExp, RExp, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003638 return Res;
3639 }
3640
3641 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003642 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003643 Res = MCUnaryExpr::create(UN->getOpcode(), UnExp, getContext());
Jack Carterd0bd6422013-04-18 00:41:53 +00003644 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00003645 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003646 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00003647 return Expr;
3648}
3649
3650bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
3651
3652 switch (Expr->getKind()) {
3653 case MCExpr::Constant:
3654 return true;
3655 case MCExpr::SymbolRef:
3656 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
3657 case MCExpr::Binary:
3658 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
3659 if (!isEvaluated(BE->getLHS()))
3660 return false;
3661 return isEvaluated(BE->getRHS());
3662 }
3663 case MCExpr::Unary:
3664 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00003665 case MCExpr::Target:
3666 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003667 }
Jack Carterb5cf5902013-04-17 00:18:04 +00003668 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00003669}
Jack Carterd0bd6422013-04-18 00:41:53 +00003670
Jack Carterb5cf5902013-04-17 00:18:04 +00003671bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003672 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00003673 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00003674 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00003675 if (Tok.isNot(AsmToken::Identifier))
3676 return true;
3677
Yaron Keren075759a2015-03-30 15:42:36 +00003678 std::string Str = Tok.getIdentifier();
Jack Carterb5cf5902013-04-17 00:18:04 +00003679
Jack Carterd0bd6422013-04-18 00:41:53 +00003680 Parser.Lex(); // Eat the identifier.
3681 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003682 const MCExpr *IdVal;
3683 SMLoc EndLoc;
3684
3685 if (getLexer().getKind() == AsmToken::LParen) {
3686 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003687 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003688 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003689 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003690 const AsmToken &nextTok = Parser.getTok();
3691 if (nextTok.isNot(AsmToken::Identifier))
3692 return true;
3693 Str += "(%";
3694 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00003695 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00003696 if (getLexer().getKind() != AsmToken::LParen)
3697 return true;
3698 } else
3699 break;
3700 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003701 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00003702 return true;
3703
3704 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00003705 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003706
3707 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00003708 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003709
Jack Carterd0bd6422013-04-18 00:41:53 +00003710 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00003711 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003712}
3713
Jack Carterb4dbc172012-09-05 23:34:03 +00003714bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
3715 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003716 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00003717 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003718 if (ResTy == MatchOperand_Success) {
3719 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00003720 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003721 StartLoc = Operand.getStartLoc();
3722 EndLoc = Operand.getEndLoc();
3723
3724 // AFAIK, we only support numeric registers and named GPR's in CFI
3725 // directives.
3726 // Don't worry about eating tokens before failing. Using an unrecognised
3727 // register is a parse error.
3728 if (Operand.isGPRAsmReg()) {
3729 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003730 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003731 }
3732
3733 return (RegNo == (unsigned)-1);
3734 }
3735
3736 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00003737 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00003738}
3739
Jack Carterb5cf5902013-04-17 00:18:04 +00003740bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003741 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00003742 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00003743 bool Result = true;
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003744 unsigned NumOfLParen = 0;
Jack Carterb5cf5902013-04-17 00:18:04 +00003745
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003746 while (getLexer().getKind() == AsmToken::LParen) {
Jack Carterb5cf5902013-04-17 00:18:04 +00003747 Parser.Lex();
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003748 ++NumOfLParen;
3749 }
Jack Carter873c7242013-01-12 01:03:14 +00003750
Jack Carterd0bd6422013-04-18 00:41:53 +00003751 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00003752 default:
3753 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00003754 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00003755 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00003756 case AsmToken::Integer:
3757 case AsmToken::Minus:
3758 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00003759 if (isParenExpr)
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003760 Result = getParser().parseParenExprOfDepth(NumOfLParen, Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00003761 else
3762 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00003763 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00003764 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003765 break;
Jack Carter873c7242013-01-12 01:03:14 +00003766 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00003767 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00003768 }
Jack Carterb5cf5902013-04-17 00:18:04 +00003769 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003770}
3771
David Blaikie960ea3f2014-06-08 16:18:35 +00003772MipsAsmParser::OperandMatchResultTy
3773MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003774 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003775 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00003776 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00003777 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00003778 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003779 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00003780 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00003781 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00003782
Jack Carterb5cf5902013-04-17 00:18:04 +00003783 if (getLexer().getKind() == AsmToken::LParen) {
3784 Parser.Lex();
3785 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003786 }
3787
Jack Carterb5cf5902013-04-17 00:18:04 +00003788 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003789 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00003790 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003791
Jack Carterd0bd6422013-04-18 00:41:53 +00003792 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003793 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003794 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003795 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00003796 SMLoc E =
3797 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003798 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00003799 return MatchOperand_Success;
3800 }
3801 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003802 SMLoc E =
3803 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00003804
Jack Carterd0bd6422013-04-18 00:41:53 +00003805 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00003806 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00003807 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00003808 S, E, *this);
3809 Operands.push_back(
3810 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00003811 return MatchOperand_Success;
3812 }
3813 Error(Parser.getTok().getLoc(), "'(' expected");
3814 return MatchOperand_ParseFail;
3815 }
3816
Jack Carterd0bd6422013-04-18 00:41:53 +00003817 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003818 }
3819
Toma Tabacu13964452014-09-04 13:23:44 +00003820 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003821 if (Res != MatchOperand_Success)
3822 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003823
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003824 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00003825 Error(Parser.getTok().getLoc(), "')' expected");
3826 return MatchOperand_ParseFail;
3827 }
3828
Jack Carter873c7242013-01-12 01:03:14 +00003829 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3830
Jack Carterd0bd6422013-04-18 00:41:53 +00003831 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003832
Craig Topper062a2ba2014-04-25 05:30:21 +00003833 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003834 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00003835
Jack Carterd0bd6422013-04-18 00:41:53 +00003836 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00003837 std::unique_ptr<MipsOperand> op(
3838 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00003839 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00003840 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003841 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00003842 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003843 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
3844 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00003845 if (IdVal->evaluateAsAbsolute(Imm))
3846 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003847 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003848 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00003849 getContext());
3850 }
3851
David Blaikie960ea3f2014-06-08 16:18:35 +00003852 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003853 return MatchOperand_Success;
3854}
3855
David Blaikie960ea3f2014-06-08 16:18:35 +00003856bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003857 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00003858 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00003859 if (Sym) {
3860 SMLoc S = Parser.getTok().getLoc();
3861 const MCExpr *Expr;
3862 if (Sym->isVariable())
3863 Expr = Sym->getVariableValue();
3864 else
3865 return false;
3866 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003867 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00003868 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00003869 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003870 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00003871 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00003872 if (ResTy == MatchOperand_Success) {
3873 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00003874 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00003875 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003876 llvm_unreachable("Should never ParseFail");
3877 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00003878 }
3879 } else if (Expr->getKind() == MCExpr::Constant) {
3880 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00003881 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00003882 Operands.push_back(
3883 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00003884 return true;
3885 }
3886 }
3887 return false;
3888}
Jack Carterd0bd6422013-04-18 00:41:53 +00003889
Jack Carter873c7242013-01-12 01:03:14 +00003890MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003891MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00003892 StringRef Identifier,
3893 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003894 int Index = matchCPURegisterName(Identifier);
3895 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003896 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003897 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3898 return MatchOperand_Success;
3899 }
3900
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003901 Index = matchHWRegsRegisterName(Identifier);
3902 if (Index != -1) {
3903 Operands.push_back(MipsOperand::createHWRegsReg(
3904 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3905 return MatchOperand_Success;
3906 }
3907
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003908 Index = matchFPURegisterName(Identifier);
3909 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003910 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003911 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3912 return MatchOperand_Success;
3913 }
3914
3915 Index = matchFCCRegisterName(Identifier);
3916 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003917 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003918 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3919 return MatchOperand_Success;
3920 }
3921
3922 Index = matchACRegisterName(Identifier);
3923 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003924 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003925 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3926 return MatchOperand_Success;
3927 }
3928
3929 Index = matchMSA128RegisterName(Identifier);
3930 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003931 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003932 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3933 return MatchOperand_Success;
3934 }
3935
3936 Index = matchMSA128CtrlRegisterName(Identifier);
3937 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003938 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003939 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3940 return MatchOperand_Success;
3941 }
3942
3943 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00003944}
3945
3946MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003947MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003948 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00003949 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003950
3951 if (Token.is(AsmToken::Identifier)) {
3952 DEBUG(dbgs() << ".. identifier\n");
3953 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00003954 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00003955 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00003956 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003957 } else if (Token.is(AsmToken::Integer)) {
3958 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00003959 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003960 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
3961 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003962 return MatchOperand_Success;
3963 }
3964
3965 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
3966
3967 return MatchOperand_NoMatch;
3968}
3969
David Blaikie960ea3f2014-06-08 16:18:35 +00003970MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003971MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003972 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00003973 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003974
3975 auto Token = Parser.getTok();
3976
3977 SMLoc S = Token.getLoc();
3978
3979 if (Token.isNot(AsmToken::Dollar)) {
3980 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
3981 if (Token.is(AsmToken::Identifier)) {
3982 if (searchSymbolAlias(Operands))
3983 return MatchOperand_Success;
3984 }
3985 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
3986 return MatchOperand_NoMatch;
3987 }
3988 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003989
Toma Tabacu13964452014-09-04 13:23:44 +00003990 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00003991 if (ResTy == MatchOperand_Success) {
3992 Parser.Lex(); // $
3993 Parser.Lex(); // identifier
3994 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003995 return ResTy;
3996}
3997
3998MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003999MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004000 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004001 switch (getLexer().getKind()) {
4002 default:
4003 return MatchOperand_NoMatch;
4004 case AsmToken::LParen:
4005 case AsmToken::Minus:
4006 case AsmToken::Plus:
4007 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00004008 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004009 case AsmToken::String:
4010 break;
4011 }
4012
4013 const MCExpr *IdVal;
4014 SMLoc S = Parser.getTok().getLoc();
4015 if (getParser().parseExpression(IdVal))
4016 return MatchOperand_ParseFail;
4017
4018 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4019 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
4020 return MatchOperand_Success;
4021}
4022
David Blaikie960ea3f2014-06-08 16:18:35 +00004023MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004024MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004025 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004026 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004027
4028 SMLoc S = getLexer().getLoc();
4029
4030 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00004031 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004032 if (ResTy != MatchOperand_NoMatch)
4033 return ResTy;
4034
Daniel Sanders315386c2014-04-01 10:40:14 +00004035 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00004036 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00004037 if (ResTy != MatchOperand_NoMatch)
4038 return ResTy;
4039
Daniel Sandersffd84362014-04-01 10:41:48 +00004040 const MCExpr *Expr = nullptr;
4041 if (Parser.parseExpression(Expr)) {
4042 // We have no way of knowing if a symbol was consumed so we must ParseFail
4043 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004044 }
Daniel Sandersffd84362014-04-01 10:41:48 +00004045 Operands.push_back(
4046 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004047 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00004048}
4049
Vladimir Medic2b953d02013-10-01 09:48:56 +00004050MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00004051MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004052 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00004053 const MCExpr *IdVal;
4054 // If the first token is '$' we may have register operand.
4055 if (Parser.getTok().is(AsmToken::Dollar))
4056 return MatchOperand_NoMatch;
4057 SMLoc S = Parser.getTok().getLoc();
4058 if (getParser().parseExpression(IdVal))
4059 return MatchOperand_ParseFail;
4060 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00004061 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00004062 int64_t Val = MCE->getValue();
4063 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4064 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00004065 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00004066 return MatchOperand_Success;
4067}
4068
Matheus Almeida779c5932013-11-18 12:32:49 +00004069MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004070MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004071 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00004072 switch (getLexer().getKind()) {
4073 default:
4074 return MatchOperand_NoMatch;
4075 case AsmToken::LParen:
4076 case AsmToken::Plus:
4077 case AsmToken::Minus:
4078 case AsmToken::Integer:
4079 break;
4080 }
4081
4082 const MCExpr *Expr;
4083 SMLoc S = Parser.getTok().getLoc();
4084
4085 if (getParser().parseExpression(Expr))
4086 return MatchOperand_ParseFail;
4087
4088 int64_t Val;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004089 if (!Expr->evaluateAsAbsolute(Val)) {
Matheus Almeida779c5932013-11-18 12:32:49 +00004090 Error(S, "expected immediate value");
4091 return MatchOperand_ParseFail;
4092 }
4093
4094 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
4095 // and because the CPU always adds one to the immediate field, the allowed
4096 // range becomes 1..4. We'll only check the range here and will deal
4097 // with the addition/subtraction when actually decoding/encoding
4098 // the instruction.
4099 if (Val < 1 || Val > 4) {
4100 Error(S, "immediate not in range (1..4)");
4101 return MatchOperand_ParseFail;
4102 }
4103
Jack Carter3b2c96e2014-01-22 23:31:38 +00004104 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004105 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00004106 return MatchOperand_Success;
4107}
4108
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004109MipsAsmParser::OperandMatchResultTy
4110MipsAsmParser::parseRegisterList(OperandVector &Operands) {
4111 MCAsmParser &Parser = getParser();
4112 SmallVector<unsigned, 10> Regs;
4113 unsigned RegNo;
4114 unsigned PrevReg = Mips::NoRegister;
4115 bool RegRange = false;
4116 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4117
4118 if (Parser.getTok().isNot(AsmToken::Dollar))
4119 return MatchOperand_ParseFail;
4120
4121 SMLoc S = Parser.getTok().getLoc();
4122 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
4123 SMLoc E = getLexer().getLoc();
4124 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
4125 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
4126 if (RegRange) {
4127 // Remove last register operand because registers from register range
4128 // should be inserted first.
4129 if (RegNo == Mips::RA) {
4130 Regs.push_back(RegNo);
4131 } else {
4132 unsigned TmpReg = PrevReg + 1;
4133 while (TmpReg <= RegNo) {
4134 if ((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) {
4135 Error(E, "invalid register operand");
4136 return MatchOperand_ParseFail;
4137 }
4138
4139 PrevReg = TmpReg;
4140 Regs.push_back(TmpReg++);
4141 }
4142 }
4143
4144 RegRange = false;
4145 } else {
4146 if ((PrevReg == Mips::NoRegister) && (RegNo != Mips::S0) &&
4147 (RegNo != Mips::RA)) {
4148 Error(E, "$16 or $31 expected");
4149 return MatchOperand_ParseFail;
4150 } else if (((RegNo < Mips::S0) || (RegNo > Mips::S7)) &&
4151 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
4152 Error(E, "invalid register operand");
4153 return MatchOperand_ParseFail;
4154 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
4155 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
4156 Error(E, "consecutive register numbers expected");
4157 return MatchOperand_ParseFail;
4158 }
4159
4160 Regs.push_back(RegNo);
4161 }
4162
4163 if (Parser.getTok().is(AsmToken::Minus))
4164 RegRange = true;
4165
4166 if (!Parser.getTok().isNot(AsmToken::Minus) &&
4167 !Parser.getTok().isNot(AsmToken::Comma)) {
4168 Error(E, "',' or '-' expected");
4169 return MatchOperand_ParseFail;
4170 }
4171
4172 Lex(); // Consume comma or minus
4173 if (Parser.getTok().isNot(AsmToken::Dollar))
4174 break;
4175
4176 PrevReg = RegNo;
4177 }
4178
4179 SMLoc E = Parser.getTok().getLoc();
4180 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4181 parseMemOperand(Operands);
4182 return MatchOperand_Success;
4183}
4184
Zoran Jovanovic2deca342014-12-16 14:59:10 +00004185MipsAsmParser::OperandMatchResultTy
4186MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
4187 MCAsmParser &Parser = getParser();
4188
4189 SMLoc S = Parser.getTok().getLoc();
4190 if (parseAnyRegister(Operands) != MatchOperand_Success)
4191 return MatchOperand_ParseFail;
4192
4193 SMLoc E = Parser.getTok().getLoc();
4194 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
4195 unsigned Reg = Op.getGPR32Reg();
4196 Operands.pop_back();
4197 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
4198 return MatchOperand_Success;
4199}
4200
Zoran Jovanovic41688672015-02-10 16:36:20 +00004201MipsAsmParser::OperandMatchResultTy
4202MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
4203 MCAsmParser &Parser = getParser();
4204 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4205 SmallVector<unsigned, 10> Regs;
4206
4207 if (Parser.getTok().isNot(AsmToken::Dollar))
4208 return MatchOperand_ParseFail;
4209
4210 SMLoc S = Parser.getTok().getLoc();
4211
4212 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4213 return MatchOperand_ParseFail;
4214
4215 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4216 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4217 Regs.push_back(RegNo);
4218
4219 SMLoc E = Parser.getTok().getLoc();
4220 if (Parser.getTok().isNot(AsmToken::Comma)) {
4221 Error(E, "',' expected");
4222 return MatchOperand_ParseFail;
4223 }
4224
4225 // Remove comma.
4226 Parser.Lex();
4227
4228 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4229 return MatchOperand_ParseFail;
4230
4231 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4232 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4233 Regs.push_back(RegNo);
4234
4235 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4236
4237 return MatchOperand_Success;
4238}
4239
Jack Carterdc1e35d2012-09-06 20:00:02 +00004240MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
4241
Vladimir Medic4c299852013-11-06 11:27:05 +00004242 MCSymbolRefExpr::VariantKind VK =
4243 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
4244 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
4245 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
4246 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
4247 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
4248 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
4249 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
4250 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
4251 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
4252 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
4253 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
4254 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
4255 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
4256 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
4257 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
4258 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
4259 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
4260 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00004261 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
4262 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
4263 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
4264 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
4265 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
4266 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00004267 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
4268 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00004269 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00004270
Matheus Almeida2852af82014-04-22 10:15:54 +00004271 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00004272
Jack Carterdc1e35d2012-09-06 20:00:02 +00004273 return VK;
4274}
Jack Cartera63b16a2012-09-07 00:23:42 +00004275
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004276/// Sometimes (i.e. load/stores) the operand may be followed immediately by
4277/// either this.
4278/// ::= '(', register, ')'
4279/// handle it before we iterate so we don't get tripped up by the lack of
4280/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004281bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004282 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004283 if (getLexer().is(AsmToken::LParen)) {
4284 Operands.push_back(
4285 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
4286 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004287 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004288 SMLoc Loc = getLexer().getLoc();
4289 Parser.eatToEndOfStatement();
4290 return Error(Loc, "unexpected token in argument list");
4291 }
4292 if (Parser.getTok().isNot(AsmToken::RParen)) {
4293 SMLoc Loc = getLexer().getLoc();
4294 Parser.eatToEndOfStatement();
4295 return Error(Loc, "unexpected token, expected ')'");
4296 }
4297 Operands.push_back(
4298 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
4299 Parser.Lex();
4300 }
4301 return false;
4302}
4303
4304/// Sometimes (i.e. in MSA) the operand may be followed immediately by
4305/// either one of these.
4306/// ::= '[', register, ']'
4307/// ::= '[', integer, ']'
4308/// handle it before we iterate so we don't get tripped up by the lack of
4309/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004310bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00004311 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004312 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004313 if (getLexer().is(AsmToken::LBrac)) {
4314 Operands.push_back(
4315 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
4316 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004317 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004318 SMLoc Loc = getLexer().getLoc();
4319 Parser.eatToEndOfStatement();
4320 return Error(Loc, "unexpected token in argument list");
4321 }
4322 if (Parser.getTok().isNot(AsmToken::RBrac)) {
4323 SMLoc Loc = getLexer().getLoc();
4324 Parser.eatToEndOfStatement();
4325 return Error(Loc, "unexpected token, expected ']'");
4326 }
4327 Operands.push_back(
4328 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
4329 Parser.Lex();
4330 }
4331 return false;
4332}
4333
David Blaikie960ea3f2014-06-08 16:18:35 +00004334bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
4335 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004336 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004337 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004338
4339 // We have reached first instruction, module directive are now forbidden.
4340 getTargetStreamer().forbidModuleDirective();
4341
Vladimir Medic74593e62013-07-17 15:00:42 +00004342 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00004343 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00004344 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00004345 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00004346 }
Vladimir Medic64828a12013-07-16 10:07:14 +00004347 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004348 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004349
4350 // Read the remaining operands.
4351 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4352 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004353 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004354 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004355 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004356 return Error(Loc, "unexpected token in argument list");
4357 }
Toma Tabacu13964452014-09-04 13:23:44 +00004358 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004359 return true;
4360 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00004361
Jack Carterd0bd6422013-04-18 00:41:53 +00004362 while (getLexer().is(AsmToken::Comma)) {
4363 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00004364 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004365 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004366 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004367 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004368 return Error(Loc, "unexpected token in argument list");
4369 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004370 // Parse bracket and parenthesis suffixes before we iterate
4371 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00004372 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004373 return true;
4374 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00004375 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004376 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00004377 }
4378 }
Jack Carterb4dbc172012-09-05 23:34:03 +00004379 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4380 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004381 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004382 return Error(Loc, "unexpected token in argument list");
4383 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004384 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00004385 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00004386}
4387
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004388bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004389 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004390 SMLoc Loc = getLexer().getLoc();
4391 Parser.eatToEndOfStatement();
4392 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00004393}
4394
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004395bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004396 return Error(Loc, ErrorMsg);
4397}
4398
Jack Carter0b744b32012-10-04 02:29:46 +00004399bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004400 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004401 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00004402
4403 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00004404 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00004405
4406 Parser.Lex(); // Eat "noat".
4407
Jack Carterd0bd6422013-04-18 00:41:53 +00004408 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004409 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004410 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004411 return false;
4412 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004413
4414 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004415 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004416 return false;
4417}
Jack Carterd0bd6422013-04-18 00:41:53 +00004418
Jack Carter0b744b32012-10-04 02:29:46 +00004419bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00004420 // Line can be: ".set at", which sets $at to $1
4421 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00004422 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00004423 Parser.Lex(); // Eat "at".
4424
Jack Carter0b744b32012-10-04 02:29:46 +00004425 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004426 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00004427 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00004428
4429 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004430 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004431 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00004432 }
4433
4434 if (getLexer().isNot(AsmToken::Equal)) {
4435 reportParseError("unexpected token, expected equals sign");
4436 return false;
4437 }
4438 Parser.Lex(); // Eat "=".
4439
4440 if (getLexer().isNot(AsmToken::Dollar)) {
4441 if (getLexer().is(AsmToken::EndOfStatement)) {
4442 reportParseError("no register specified");
4443 return false;
4444 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00004445 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00004446 return false;
4447 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004448 }
4449 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00004450
Toma Tabacu16a74492015-02-13 10:30:57 +00004451 // Find out what "reg" is.
4452 unsigned AtRegNo;
4453 const AsmToken &Reg = Parser.getTok();
4454 if (Reg.is(AsmToken::Identifier)) {
4455 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
4456 } else if (Reg.is(AsmToken::Integer)) {
4457 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00004458 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00004459 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00004460 return false;
4461 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004462
4463 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00004464 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004465 reportParseError("invalid register");
4466 return false;
4467 }
4468 Parser.Lex(); // Eat "reg".
4469
4470 // If this is not the end of the statement, report an error.
4471 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4472 reportParseError("unexpected token, expected end of statement");
4473 return false;
4474 }
4475
4476 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
4477
4478 Parser.Lex(); // Consume the EndOfStatement.
4479 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004480}
4481
4482bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004483 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004484 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004485 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004486 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004487 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004488 return false;
4489 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004490 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00004491 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004492 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004493 return false;
4494}
4495
4496bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004497 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004498 Parser.Lex();
4499 // If this is not the end of the statement, report an error.
4500 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004501 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004502 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00004503 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004504 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00004505 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004506 Parser.Lex(); // Consume the EndOfStatement.
4507 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004508}
4509
4510bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004511 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004512 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004513 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004514 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004515 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004516 return false;
4517 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004518 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00004519 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00004520 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004521 return false;
4522}
4523
4524bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004525 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004526 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004527 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004528 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004529 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004530 return false;
4531 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004532 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00004533 reportParseError("`noreorder' must be set before `nomacro'");
4534 return false;
4535 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004536 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00004537 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00004538 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004539 return false;
4540}
Jack Carterd76b2372013-03-21 21:44:16 +00004541
Daniel Sanders44934432014-08-07 12:03:36 +00004542bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004543 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00004544 Parser.Lex();
4545
4546 // If this is not the end of the statement, report an error.
4547 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004548 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00004549
4550 setFeatureBits(Mips::FeatureMSA, "msa");
4551 getTargetStreamer().emitDirectiveSetMsa();
4552 return false;
4553}
4554
4555bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004556 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00004557 Parser.Lex();
4558
4559 // If this is not the end of the statement, report an error.
4560 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004561 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00004562
4563 clearFeatureBits(Mips::FeatureMSA, "msa");
4564 getTargetStreamer().emitDirectiveSetNoMsa();
4565 return false;
4566}
4567
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004568bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004569 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004570 Parser.Lex(); // Eat "nodsp".
4571
4572 // If this is not the end of the statement, report an error.
4573 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4574 reportParseError("unexpected token, expected end of statement");
4575 return false;
4576 }
4577
4578 clearFeatureBits(Mips::FeatureDSP, "dsp");
4579 getTargetStreamer().emitDirectiveSetNoDsp();
4580 return false;
4581}
4582
Toma Tabacucc2502d2014-11-04 17:18:07 +00004583bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004584 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00004585 Parser.Lex(); // Eat "mips16".
4586
Jack Carter39536722014-01-22 23:08:42 +00004587 // If this is not the end of the statement, report an error.
4588 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004589 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00004590 return false;
4591 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00004592
4593 setFeatureBits(Mips::FeatureMips16, "mips16");
4594 getTargetStreamer().emitDirectiveSetMips16();
4595 Parser.Lex(); // Consume the EndOfStatement.
4596 return false;
4597}
4598
4599bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004600 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00004601 Parser.Lex(); // Eat "nomips16".
4602
4603 // If this is not the end of the statement, report an error.
4604 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4605 reportParseError("unexpected token, expected end of statement");
4606 return false;
4607 }
4608
4609 clearFeatureBits(Mips::FeatureMips16, "mips16");
4610 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00004611 Parser.Lex(); // Consume the EndOfStatement.
4612 return false;
4613}
4614
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004615bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004616 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004617 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004618 // Line can be: .set fp=32
4619 // .set fp=xx
4620 // .set fp=64
4621 Parser.Lex(); // Eat fp token
4622 AsmToken Tok = Parser.getTok();
4623 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004624 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004625 return false;
4626 }
4627 Parser.Lex(); // Eat '=' token.
4628 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004629
4630 if (!parseFpABIValue(FpAbiVal, ".set"))
4631 return false;
4632
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004633 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004634 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004635 return false;
4636 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004637 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004638 Parser.Lex(); // Consume the EndOfStatement.
4639 return false;
4640}
4641
Toma Tabacu32c72aa2015-06-30 09:36:50 +00004642bool MipsAsmParser::parseSetOddSPRegDirective() {
4643 MCAsmParser &Parser = getParser();
4644
4645 Parser.Lex(); // Eat "oddspreg".
4646 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4647 reportParseError("unexpected token, expected end of statement");
4648 return false;
4649 }
4650
4651 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4652 getTargetStreamer().emitDirectiveSetOddSPReg();
4653 return false;
4654}
4655
4656bool MipsAsmParser::parseSetNoOddSPRegDirective() {
4657 MCAsmParser &Parser = getParser();
4658
4659 Parser.Lex(); // Eat "nooddspreg".
4660 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4661 reportParseError("unexpected token, expected end of statement");
4662 return false;
4663 }
4664
4665 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4666 getTargetStreamer().emitDirectiveSetNoOddSPReg();
4667 return false;
4668}
4669
Toma Tabacu9db22db2014-09-09 10:15:38 +00004670bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004671 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00004672 SMLoc Loc = getLexer().getLoc();
4673
4674 Parser.Lex();
4675 if (getLexer().isNot(AsmToken::EndOfStatement))
4676 return reportParseError("unexpected token, expected end of statement");
4677
4678 // Always keep an element on the options "stack" to prevent the user
4679 // from changing the initial options. This is how we remember them.
4680 if (AssemblerOptions.size() == 2)
4681 return reportParseError(Loc, ".set pop with no .set push");
4682
4683 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00004684 setAvailableFeatures(
4685 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
4686 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00004687
4688 getTargetStreamer().emitDirectiveSetPop();
4689 return false;
4690}
4691
4692bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004693 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00004694 Parser.Lex();
4695 if (getLexer().isNot(AsmToken::EndOfStatement))
4696 return reportParseError("unexpected token, expected end of statement");
4697
4698 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00004699 AssemblerOptions.push_back(
4700 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00004701
4702 getTargetStreamer().emitDirectiveSetPush();
4703 return false;
4704}
4705
Toma Tabacu29696502015-06-02 09:48:04 +00004706bool MipsAsmParser::parseSetSoftFloatDirective() {
4707 MCAsmParser &Parser = getParser();
4708 Parser.Lex();
4709 if (getLexer().isNot(AsmToken::EndOfStatement))
4710 return reportParseError("unexpected token, expected end of statement");
4711
4712 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
4713 getTargetStreamer().emitDirectiveSetSoftFloat();
4714 return false;
4715}
4716
4717bool MipsAsmParser::parseSetHardFloatDirective() {
4718 MCAsmParser &Parser = getParser();
4719 Parser.Lex();
4720 if (getLexer().isNot(AsmToken::EndOfStatement))
4721 return reportParseError("unexpected token, expected end of statement");
4722
4723 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
4724 getTargetStreamer().emitDirectiveSetHardFloat();
4725 return false;
4726}
4727
Jack Carterd76b2372013-03-21 21:44:16 +00004728bool MipsAsmParser::parseSetAssignment() {
4729 StringRef Name;
4730 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00004731 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00004732
4733 if (Parser.parseIdentifier(Name))
4734 reportParseError("expected identifier after .set");
4735
4736 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00004737 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00004738 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00004739
Jack Carter3b2c96e2014-01-22 23:31:38 +00004740 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00004741 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00004742
Jim Grosbach6f482002015-05-18 18:43:14 +00004743 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00004744 Sym->setVariableValue(Value);
4745
4746 return false;
4747}
Jack Carterd0bd6422013-04-18 00:41:53 +00004748
Toma Tabacu26647792014-09-09 12:52:14 +00004749bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004750 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00004751 Parser.Lex();
4752 if (getLexer().isNot(AsmToken::EndOfStatement))
4753 return reportParseError("unexpected token, expected end of statement");
4754
4755 // Reset assembler options to their initial values.
Toma Tabacu465acfd2015-06-09 13:33:26 +00004756 setAvailableFeatures(
4757 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
4758 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00004759 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
4760
4761 getTargetStreamer().emitDirectiveSetMips0();
4762 return false;
4763}
4764
Toma Tabacu85618b32014-08-19 14:22:52 +00004765bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004766 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00004767 Parser.Lex();
4768 if (getLexer().isNot(AsmToken::Equal))
4769 return reportParseError("unexpected token, expected equals sign");
4770
4771 Parser.Lex();
4772 StringRef Arch;
4773 if (Parser.parseIdentifier(Arch))
4774 return reportParseError("expected arch identifier");
4775
4776 StringRef ArchFeatureName =
4777 StringSwitch<StringRef>(Arch)
4778 .Case("mips1", "mips1")
4779 .Case("mips2", "mips2")
4780 .Case("mips3", "mips3")
4781 .Case("mips4", "mips4")
4782 .Case("mips5", "mips5")
4783 .Case("mips32", "mips32")
4784 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00004785 .Case("mips32r3", "mips32r3")
4786 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00004787 .Case("mips32r6", "mips32r6")
4788 .Case("mips64", "mips64")
4789 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00004790 .Case("mips64r3", "mips64r3")
4791 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00004792 .Case("mips64r6", "mips64r6")
4793 .Case("cnmips", "cnmips")
4794 .Case("r4000", "mips3") // This is an implementation of Mips3.
4795 .Default("");
4796
4797 if (ArchFeatureName.empty())
4798 return reportParseError("unsupported architecture");
4799
4800 selectArch(ArchFeatureName);
4801 getTargetStreamer().emitDirectiveSetArch(Arch);
4802 return false;
4803}
4804
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004805bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004806 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004807 Parser.Lex();
4808 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004809 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004810
Matheus Almeida2852af82014-04-22 10:15:54 +00004811 switch (Feature) {
4812 default:
4813 llvm_unreachable("Unimplemented feature");
4814 case Mips::FeatureDSP:
4815 setFeatureBits(Mips::FeatureDSP, "dsp");
4816 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004817 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004818 case Mips::FeatureMicroMips:
4819 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004820 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004821 case Mips::FeatureMips1:
4822 selectArch("mips1");
4823 getTargetStreamer().emitDirectiveSetMips1();
4824 break;
4825 case Mips::FeatureMips2:
4826 selectArch("mips2");
4827 getTargetStreamer().emitDirectiveSetMips2();
4828 break;
4829 case Mips::FeatureMips3:
4830 selectArch("mips3");
4831 getTargetStreamer().emitDirectiveSetMips3();
4832 break;
4833 case Mips::FeatureMips4:
4834 selectArch("mips4");
4835 getTargetStreamer().emitDirectiveSetMips4();
4836 break;
4837 case Mips::FeatureMips5:
4838 selectArch("mips5");
4839 getTargetStreamer().emitDirectiveSetMips5();
4840 break;
4841 case Mips::FeatureMips32:
4842 selectArch("mips32");
4843 getTargetStreamer().emitDirectiveSetMips32();
4844 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004845 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004846 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00004847 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004848 break;
Daniel Sanders17793142015-02-18 16:24:50 +00004849 case Mips::FeatureMips32r3:
4850 selectArch("mips32r3");
4851 getTargetStreamer().emitDirectiveSetMips32R3();
4852 break;
4853 case Mips::FeatureMips32r5:
4854 selectArch("mips32r5");
4855 getTargetStreamer().emitDirectiveSetMips32R5();
4856 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004857 case Mips::FeatureMips32r6:
4858 selectArch("mips32r6");
4859 getTargetStreamer().emitDirectiveSetMips32R6();
4860 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004861 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004862 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00004863 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00004864 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004865 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004866 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00004867 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00004868 break;
Daniel Sanders17793142015-02-18 16:24:50 +00004869 case Mips::FeatureMips64r3:
4870 selectArch("mips64r3");
4871 getTargetStreamer().emitDirectiveSetMips64R3();
4872 break;
4873 case Mips::FeatureMips64r5:
4874 selectArch("mips64r5");
4875 getTargetStreamer().emitDirectiveSetMips64R5();
4876 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004877 case Mips::FeatureMips64r6:
4878 selectArch("mips64r6");
4879 getTargetStreamer().emitDirectiveSetMips64R6();
4880 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004881 }
4882 return false;
4883}
4884
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004885bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004886 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004887 if (getLexer().isNot(AsmToken::Comma)) {
4888 SMLoc Loc = getLexer().getLoc();
4889 Parser.eatToEndOfStatement();
4890 return Error(Loc, ErrorStr);
4891 }
4892
Matheus Almeida2852af82014-04-22 10:15:54 +00004893 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004894 return true;
4895}
4896
Daniel Sanderse2982ad2015-09-17 16:08:39 +00004897// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
4898// In this class, it is only used for .cprestore.
4899// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
4900// MipsTargetELFStreamer and MipsAsmParser.
4901bool MipsAsmParser::isPicAndNotNxxAbi() {
4902 return inPicMode() && !(isABI_N32() || isABI_N64());
4903}
4904
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004905bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00004906 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00004907 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004908
Toma Tabacudde4c462014-11-06 10:02:45 +00004909 if (inMips16Mode()) {
4910 reportParseError(".cpload is not supported in Mips16 mode");
4911 return false;
4912 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004913
David Blaikie960ea3f2014-06-08 16:18:35 +00004914 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00004915 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004916 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4917 reportParseError("expected register containing function address");
4918 return false;
4919 }
4920
David Blaikie960ea3f2014-06-08 16:18:35 +00004921 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
4922 if (!RegOpnd.isGPRAsmReg()) {
4923 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004924 return false;
4925 }
4926
Toma Tabacudde4c462014-11-06 10:02:45 +00004927 // If this is not the end of the statement, report an error.
4928 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4929 reportParseError("unexpected token, expected end of statement");
4930 return false;
4931 }
4932
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004933 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004934 return false;
4935}
4936
Daniel Sanderse2982ad2015-09-17 16:08:39 +00004937bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
4938 MCAsmParser &Parser = getParser();
4939
4940 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
4941 // is used in non-PIC mode.
4942
4943 if (inMips16Mode()) {
4944 reportParseError(".cprestore is not supported in Mips16 mode");
4945 return false;
4946 }
4947
4948 // Get the stack offset value.
4949 const MCExpr *StackOffset;
4950 int64_t StackOffsetVal;
4951 if (Parser.parseExpression(StackOffset)) {
4952 reportParseError("expected stack offset value");
4953 return false;
4954 }
4955
4956 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
4957 reportParseError("stack offset is not an absolute expression");
4958 return false;
4959 }
4960
4961 if (StackOffsetVal < 0) {
4962 Warning(Loc, ".cprestore with negative stack offset has no effect");
4963 IsCpRestoreSet = false;
4964 } else {
4965 IsCpRestoreSet = true;
4966 CpRestoreOffset = StackOffsetVal;
4967 }
4968
4969 // If this is not the end of the statement, report an error.
4970 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4971 reportParseError("unexpected token, expected end of statement");
4972 return false;
4973 }
4974
4975 // Store the $gp on the stack.
4976 SmallVector<MCInst, 3> StoreInsts;
4977 createCpRestoreMemOp(false /*IsLoad*/, CpRestoreOffset /*StackOffset*/, Loc,
4978 StoreInsts);
4979
4980 getTargetStreamer().emitDirectiveCpRestore(StoreInsts, CpRestoreOffset);
4981 Parser.Lex(); // Consume the EndOfStatement.
4982 return false;
4983}
4984
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004985bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004986 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004987 unsigned FuncReg;
4988 unsigned Save;
4989 bool SaveIsReg = true;
4990
Matheus Almeida7e815762014-06-18 13:08:59 +00004991 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00004992 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00004993 if (ResTy == MatchOperand_NoMatch) {
4994 reportParseError("expected register containing function address");
4995 Parser.eatToEndOfStatement();
4996 return false;
4997 }
4998
4999 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5000 if (!FuncRegOpnd.isGPRAsmReg()) {
5001 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
5002 Parser.eatToEndOfStatement();
5003 return false;
5004 }
5005
5006 FuncReg = FuncRegOpnd.getGPR32Reg();
5007 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005008
Toma Tabacu65f10572014-09-16 15:00:52 +00005009 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005010 return true;
5011
Toma Tabacu13964452014-09-04 13:23:44 +00005012 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005013 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00005014 const MCExpr *OffsetExpr;
5015 int64_t OffsetVal;
5016 SMLoc ExprLoc = getLexer().getLoc();
5017
5018 if (Parser.parseExpression(OffsetExpr) ||
5019 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
5020 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00005021 Parser.eatToEndOfStatement();
5022 return false;
5023 }
Daniel Sanders5d796282015-09-21 09:26:55 +00005024
5025 Save = OffsetVal;
5026 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00005027 } else {
5028 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5029 if (!SaveOpnd.isGPRAsmReg()) {
5030 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
5031 Parser.eatToEndOfStatement();
5032 return false;
5033 }
5034 Save = SaveOpnd.getGPR32Reg();
5035 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005036
Toma Tabacu65f10572014-09-16 15:00:52 +00005037 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005038 return true;
5039
Toma Tabacu8874eac2015-02-18 13:46:53 +00005040 const MCExpr *Expr;
5041 if (Parser.parseExpression(Expr)) {
5042 reportParseError("expected expression");
5043 return false;
5044 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005045
Toma Tabacu8874eac2015-02-18 13:46:53 +00005046 if (Expr->getKind() != MCExpr::SymbolRef) {
5047 reportParseError("expected symbol");
5048 return false;
5049 }
5050 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
5051
Daniel Sandersf173dda2015-09-22 10:50:09 +00005052 CpSaveLocation = Save;
5053 CpSaveLocationIsRegister = SaveIsReg;
5054
Toma Tabacu8874eac2015-02-18 13:46:53 +00005055 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
5056 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005057 return false;
5058}
5059
Daniel Sandersf173dda2015-09-22 10:50:09 +00005060bool MipsAsmParser::parseDirectiveCPReturn() {
5061 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
5062 CpSaveLocationIsRegister);
5063 return false;
5064}
5065
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005066bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005067 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005068 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5069 const AsmToken &Tok = Parser.getTok();
5070
5071 if (Tok.getString() == "2008") {
5072 Parser.Lex();
5073 getTargetStreamer().emitDirectiveNaN2008();
5074 return false;
5075 } else if (Tok.getString() == "legacy") {
5076 Parser.Lex();
5077 getTargetStreamer().emitDirectiveNaNLegacy();
5078 return false;
5079 }
5080 }
5081 // If we don't recognize the option passed to the .nan
5082 // directive (e.g. no option or unknown option), emit an error.
5083 reportParseError("invalid option in .nan directive");
5084 return false;
5085}
5086
Jack Carter0b744b32012-10-04 02:29:46 +00005087bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005088 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005089 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00005090 const AsmToken &Tok = Parser.getTok();
5091
5092 if (Tok.getString() == "noat") {
5093 return parseSetNoAtDirective();
5094 } else if (Tok.getString() == "at") {
5095 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00005096 } else if (Tok.getString() == "arch") {
5097 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005098 } else if (Tok.getString() == "fp") {
5099 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005100 } else if (Tok.getString() == "oddspreg") {
5101 return parseSetOddSPRegDirective();
5102 } else if (Tok.getString() == "nooddspreg") {
5103 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005104 } else if (Tok.getString() == "pop") {
5105 return parseSetPopDirective();
5106 } else if (Tok.getString() == "push") {
5107 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00005108 } else if (Tok.getString() == "reorder") {
5109 return parseSetReorderDirective();
5110 } else if (Tok.getString() == "noreorder") {
5111 return parseSetNoReorderDirective();
5112 } else if (Tok.getString() == "macro") {
5113 return parseSetMacroDirective();
5114 } else if (Tok.getString() == "nomacro") {
5115 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00005116 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00005117 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005118 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00005119 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005120 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00005121 getTargetStreamer().emitDirectiveSetNoMicroMips();
5122 Parser.eatToEndOfStatement();
5123 return false;
5124 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005125 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00005126 } else if (Tok.getString() == "mips0") {
5127 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00005128 } else if (Tok.getString() == "mips1") {
5129 return parseSetFeature(Mips::FeatureMips1);
5130 } else if (Tok.getString() == "mips2") {
5131 return parseSetFeature(Mips::FeatureMips2);
5132 } else if (Tok.getString() == "mips3") {
5133 return parseSetFeature(Mips::FeatureMips3);
5134 } else if (Tok.getString() == "mips4") {
5135 return parseSetFeature(Mips::FeatureMips4);
5136 } else if (Tok.getString() == "mips5") {
5137 return parseSetFeature(Mips::FeatureMips5);
5138 } else if (Tok.getString() == "mips32") {
5139 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00005140 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005141 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005142 } else if (Tok.getString() == "mips32r3") {
5143 return parseSetFeature(Mips::FeatureMips32r3);
5144 } else if (Tok.getString() == "mips32r5") {
5145 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005146 } else if (Tok.getString() == "mips32r6") {
5147 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005148 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005149 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005150 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005151 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005152 } else if (Tok.getString() == "mips64r3") {
5153 return parseSetFeature(Mips::FeatureMips64r3);
5154 } else if (Tok.getString() == "mips64r5") {
5155 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005156 } else if (Tok.getString() == "mips64r6") {
5157 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00005158 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005159 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005160 } else if (Tok.getString() == "nodsp") {
5161 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00005162 } else if (Tok.getString() == "msa") {
5163 return parseSetMsaDirective();
5164 } else if (Tok.getString() == "nomsa") {
5165 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00005166 } else if (Tok.getString() == "softfloat") {
5167 return parseSetSoftFloatDirective();
5168 } else if (Tok.getString() == "hardfloat") {
5169 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00005170 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00005171 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00005172 parseSetAssignment();
5173 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005174 }
Jack Carter07c818d2013-01-25 01:31:34 +00005175
Jack Carter0b744b32012-10-04 02:29:46 +00005176 return true;
5177}
5178
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005179/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00005180/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005181bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005182 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005183 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5184 for (;;) {
5185 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005186 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00005187 return true;
5188
5189 getParser().getStreamer().EmitValue(Value, Size);
5190
5191 if (getLexer().is(AsmToken::EndOfStatement))
5192 break;
5193
Jack Carter07c818d2013-01-25 01:31:34 +00005194 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005195 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00005196 Parser.Lex();
5197 }
5198 }
5199
5200 Parser.Lex();
5201 return false;
5202}
5203
Vladimir Medic4c299852013-11-06 11:27:05 +00005204/// parseDirectiveGpWord
5205/// ::= .gpword local_sym
5206bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005207 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00005208 const MCExpr *Value;
5209 // EmitGPRel32Value requires an expression, so we are using base class
5210 // method to evaluate the expression.
5211 if (getParser().parseExpression(Value))
5212 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00005213 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00005214
Vladimir Medice10c1122013-11-13 13:18:04 +00005215 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005216 return Error(getLexer().getLoc(),
5217 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00005218 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00005219 return false;
5220}
5221
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005222/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00005223/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005224bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005225 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005226 const MCExpr *Value;
5227 // EmitGPRel64Value requires an expression, so we are using base class
5228 // method to evaluate the expression.
5229 if (getParser().parseExpression(Value))
5230 return true;
5231 getParser().getStreamer().EmitGPRel64Value(Value);
5232
5233 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005234 return Error(getLexer().getLoc(),
5235 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00005236 Parser.Lex(); // Eat EndOfStatement token.
5237 return false;
5238}
5239
Jack Carter0cd3c192014-01-06 23:27:31 +00005240bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005241 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00005242 // Get the option token.
5243 AsmToken Tok = Parser.getTok();
5244 // At the moment only identifiers are supported.
5245 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005246 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00005247 Parser.eatToEndOfStatement();
5248 return false;
5249 }
5250
5251 StringRef Option = Tok.getIdentifier();
5252
5253 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005254 // MipsAsmParser needs to know if the current PIC mode changes.
5255 IsPicEnabled = false;
5256
Jack Carter0cd3c192014-01-06 23:27:31 +00005257 getTargetStreamer().emitDirectiveOptionPic0();
5258 Parser.Lex();
5259 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5260 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005261 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005262 Parser.eatToEndOfStatement();
5263 }
5264 return false;
5265 }
5266
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005267 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005268 // MipsAsmParser needs to know if the current PIC mode changes.
5269 IsPicEnabled = true;
5270
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005271 getTargetStreamer().emitDirectiveOptionPic2();
5272 Parser.Lex();
5273 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5274 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005275 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005276 Parser.eatToEndOfStatement();
5277 }
5278 return false;
5279 }
5280
Jack Carter0cd3c192014-01-06 23:27:31 +00005281 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00005282 Warning(Parser.getTok().getLoc(),
5283 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00005284 Parser.eatToEndOfStatement();
5285 return false;
5286}
5287
Toma Tabacu9ca50962015-04-16 09:53:47 +00005288/// parseInsnDirective
5289/// ::= .insn
5290bool MipsAsmParser::parseInsnDirective() {
5291 // If this is not the end of the statement, report an error.
5292 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5293 reportParseError("unexpected token, expected end of statement");
5294 return false;
5295 }
5296
5297 // The actual label marking happens in
5298 // MipsELFStreamer::createPendingLabelRelocs().
5299 getTargetStreamer().emitDirectiveInsn();
5300
5301 getParser().Lex(); // Eat EndOfStatement token.
5302 return false;
5303}
5304
Daniel Sanders7e527422014-07-10 13:38:23 +00005305/// parseDirectiveModule
5306/// ::= .module oddspreg
5307/// ::= .module nooddspreg
5308/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00005309/// ::= .module softfloat
5310/// ::= .module hardfloat
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005311bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005312 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005313 MCAsmLexer &Lexer = getLexer();
5314 SMLoc L = Lexer.getLoc();
5315
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00005316 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005317 // TODO : get a better message.
5318 reportParseError(".module directive must appear before any code");
5319 return false;
5320 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005321
Toma Tabacuc405c822015-01-23 10:40:19 +00005322 StringRef Option;
5323 if (Parser.parseIdentifier(Option)) {
5324 reportParseError("expected .module option identifier");
5325 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005326 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005327
Toma Tabacuc405c822015-01-23 10:40:19 +00005328 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005329 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005330
Toma Tabacu3c499582015-06-25 10:56:57 +00005331 // Synchronize the abiflags information with the FeatureBits information we
5332 // changed above.
5333 getTargetStreamer().updateABIInfo(*this);
5334
5335 // If printing assembly, use the recently updated abiflags information.
5336 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5337 // emitted at the end).
5338 getTargetStreamer().emitDirectiveModuleOddSPReg();
5339
Toma Tabacuc405c822015-01-23 10:40:19 +00005340 // If this is not the end of the statement, report an error.
5341 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5342 reportParseError("unexpected token, expected end of statement");
5343 return false;
5344 }
5345
5346 return false; // parseDirectiveModule has finished successfully.
5347 } else if (Option == "nooddspreg") {
5348 if (!isABI_O32()) {
5349 Error(L, "'.module nooddspreg' requires the O32 ABI");
5350 return false;
5351 }
5352
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005353 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005354
Toma Tabacu3c499582015-06-25 10:56:57 +00005355 // Synchronize the abiflags information with the FeatureBits information we
5356 // changed above.
5357 getTargetStreamer().updateABIInfo(*this);
5358
5359 // If printing assembly, use the recently updated abiflags information.
5360 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5361 // emitted at the end).
5362 getTargetStreamer().emitDirectiveModuleOddSPReg();
5363
Toma Tabacuc405c822015-01-23 10:40:19 +00005364 // If this is not the end of the statement, report an error.
5365 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5366 reportParseError("unexpected token, expected end of statement");
5367 return false;
5368 }
5369
5370 return false; // parseDirectiveModule has finished successfully.
5371 } else if (Option == "fp") {
5372 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00005373 } else if (Option == "softfloat") {
5374 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5375
5376 // Synchronize the ABI Flags information with the FeatureBits information we
5377 // updated above.
5378 getTargetStreamer().updateABIInfo(*this);
5379
5380 // If printing assembly, use the recently updated ABI Flags information.
5381 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5382 // emitted later).
5383 getTargetStreamer().emitDirectiveModuleSoftFloat();
5384
5385 // If this is not the end of the statement, report an error.
5386 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5387 reportParseError("unexpected token, expected end of statement");
5388 return false;
5389 }
5390
5391 return false; // parseDirectiveModule has finished successfully.
5392 } else if (Option == "hardfloat") {
5393 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5394
5395 // Synchronize the ABI Flags information with the FeatureBits information we
5396 // updated above.
5397 getTargetStreamer().updateABIInfo(*this);
5398
5399 // If printing assembly, use the recently updated ABI Flags information.
5400 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5401 // emitted later).
5402 getTargetStreamer().emitDirectiveModuleHardFloat();
5403
5404 // If this is not the end of the statement, report an error.
5405 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5406 reportParseError("unexpected token, expected end of statement");
5407 return false;
5408 }
5409
5410 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00005411 } else {
5412 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
5413 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005414}
5415
5416/// parseDirectiveModuleFP
5417/// ::= =32
5418/// ::= =xx
5419/// ::= =64
5420bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005421 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005422 MCAsmLexer &Lexer = getLexer();
5423
5424 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005425 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005426 return false;
5427 }
5428 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005429
Daniel Sanders7e527422014-07-10 13:38:23 +00005430 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005431 if (!parseFpABIValue(FpABI, ".module"))
5432 return false;
5433
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005434 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005435 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005436 return false;
5437 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005438
Toma Tabacua64e5402015-06-25 12:44:38 +00005439 // Synchronize the abiflags information with the FeatureBits information we
5440 // changed above.
5441 getTargetStreamer().updateABIInfo(*this);
5442
5443 // If printing assembly, use the recently updated abiflags information.
5444 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5445 // emitted at the end).
5446 getTargetStreamer().emitDirectiveModuleFP();
5447
Daniel Sanders7e527422014-07-10 13:38:23 +00005448 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005449 return false;
5450}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005451
Daniel Sanders7e527422014-07-10 13:38:23 +00005452bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005453 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005454 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005455 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005456 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005457
5458 if (Lexer.is(AsmToken::Identifier)) {
5459 StringRef Value = Parser.getTok().getString();
5460 Parser.Lex();
5461
5462 if (Value != "xx") {
5463 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5464 return false;
5465 }
5466
5467 if (!isABI_O32()) {
5468 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
5469 return false;
5470 }
5471
Daniel Sanders7e527422014-07-10 13:38:23 +00005472 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005473 if (ModuleLevelOptions) {
5474 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5475 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5476 } else {
5477 setFeatureBits(Mips::FeatureFPXX, "fpxx");
5478 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5479 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005480 return true;
5481 }
5482
5483 if (Lexer.is(AsmToken::Integer)) {
5484 unsigned Value = Parser.getTok().getIntVal();
5485 Parser.Lex();
5486
5487 if (Value != 32 && Value != 64) {
5488 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5489 return false;
5490 }
5491
5492 if (Value == 32) {
5493 if (!isABI_O32()) {
5494 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
5495 return false;
5496 }
5497
Daniel Sanders7e527422014-07-10 13:38:23 +00005498 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005499 if (ModuleLevelOptions) {
5500 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5501 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5502 } else {
5503 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
5504 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5505 }
Toma Tabacua64e5402015-06-25 12:44:38 +00005506 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00005507 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005508 if (ModuleLevelOptions) {
5509 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5510 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5511 } else {
5512 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
5513 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
5514 }
Toma Tabacua64e5402015-06-25 12:44:38 +00005515 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005516
Daniel Sanders7e527422014-07-10 13:38:23 +00005517 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005518 }
5519
5520 return false;
5521}
5522
Jack Carter0b744b32012-10-04 02:29:46 +00005523bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005524 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005525 StringRef IDVal = DirectiveID.getString();
5526
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005527 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005528 return parseDirectiveCpLoad(DirectiveID.getLoc());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005529 if (IDVal == ".cprestore")
5530 return parseDirectiveCpRestore(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00005531 if (IDVal == ".dword") {
5532 parseDataDirective(8, DirectiveID.getLoc());
5533 return false;
5534 }
Jack Carterd0bd6422013-04-18 00:41:53 +00005535 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005536 StringRef SymbolName;
5537
5538 if (Parser.parseIdentifier(SymbolName)) {
5539 reportParseError("expected identifier after .ent");
5540 return false;
5541 }
5542
5543 // There's an undocumented extension that allows an integer to
5544 // follow the name of the procedure which AFAICS is ignored by GAS.
5545 // Example: .ent foo,2
5546 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5547 if (getLexer().isNot(AsmToken::Comma)) {
5548 // Even though we accept this undocumented extension for compatibility
5549 // reasons, the additional integer argument does not actually change
5550 // the behaviour of the '.ent' directive, so we would like to discourage
5551 // its use. We do this by not referring to the extended version in
5552 // error messages which are not directly related to its use.
5553 reportParseError("unexpected token, expected end of statement");
5554 return false;
5555 }
5556 Parser.Lex(); // Eat the comma.
5557 const MCExpr *DummyNumber;
5558 int64_t DummyNumberVal;
5559 // If the user was explicitly trying to use the extended version,
5560 // we still give helpful extension-related error messages.
5561 if (Parser.parseExpression(DummyNumber)) {
5562 reportParseError("expected number after comma");
5563 return false;
5564 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00005565 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005566 reportParseError("expected an absolute expression after comma");
5567 return false;
5568 }
5569 }
5570
5571 // If this is not the end of the statement, report an error.
5572 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5573 reportParseError("unexpected token, expected end of statement");
5574 return false;
5575 }
5576
Jim Grosbach6f482002015-05-18 18:43:14 +00005577 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005578
5579 getTargetStreamer().emitDirectiveEnt(*Sym);
5580 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005581 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00005582 return false;
5583 }
5584
Jack Carter07c818d2013-01-25 01:31:34 +00005585 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005586 StringRef SymbolName;
5587
5588 if (Parser.parseIdentifier(SymbolName)) {
5589 reportParseError("expected identifier after .end");
5590 return false;
5591 }
5592
5593 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5594 reportParseError("unexpected token, expected end of statement");
5595 return false;
5596 }
5597
5598 if (CurrentFn == nullptr) {
5599 reportParseError(".end used without .ent");
5600 return false;
5601 }
5602
5603 if ((SymbolName != CurrentFn->getName())) {
5604 reportParseError(".end symbol does not match .ent symbol");
5605 return false;
5606 }
5607
5608 getTargetStreamer().emitDirectiveEnd(SymbolName);
5609 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005610 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00005611 return false;
5612 }
5613
Jack Carter07c818d2013-01-25 01:31:34 +00005614 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005615 // .frame $stack_reg, frame_size_in_bytes, $return_reg
5616 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005617 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005618 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5619 reportParseError("expected stack register");
5620 return false;
5621 }
5622
5623 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5624 if (!StackRegOpnd.isGPRAsmReg()) {
5625 reportParseError(StackRegOpnd.getStartLoc(),
5626 "expected general purpose register");
5627 return false;
5628 }
5629 unsigned StackReg = StackRegOpnd.getGPR32Reg();
5630
5631 if (Parser.getTok().is(AsmToken::Comma))
5632 Parser.Lex();
5633 else {
5634 reportParseError("unexpected token, expected comma");
5635 return false;
5636 }
5637
5638 // Parse the frame size.
5639 const MCExpr *FrameSize;
5640 int64_t FrameSizeVal;
5641
5642 if (Parser.parseExpression(FrameSize)) {
5643 reportParseError("expected frame size value");
5644 return false;
5645 }
5646
Jim Grosbach13760bd2015-05-30 01:25:56 +00005647 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005648 reportParseError("frame size not an absolute expression");
5649 return false;
5650 }
5651
5652 if (Parser.getTok().is(AsmToken::Comma))
5653 Parser.Lex();
5654 else {
5655 reportParseError("unexpected token, expected comma");
5656 return false;
5657 }
5658
5659 // Parse the return register.
5660 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00005661 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005662 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5663 reportParseError("expected return register");
5664 return false;
5665 }
5666
5667 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5668 if (!ReturnRegOpnd.isGPRAsmReg()) {
5669 reportParseError(ReturnRegOpnd.getStartLoc(),
5670 "expected general purpose register");
5671 return false;
5672 }
5673
5674 // If this is not the end of the statement, report an error.
5675 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5676 reportParseError("unexpected token, expected end of statement");
5677 return false;
5678 }
5679
5680 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
5681 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005682 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00005683 return false;
5684 }
5685
Jack Carter07c818d2013-01-25 01:31:34 +00005686 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00005687 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00005688 }
5689
Daniel Sandersd97a6342014-08-13 10:07:34 +00005690 if (IDVal == ".mask" || IDVal == ".fmask") {
5691 // .mask bitmask, frame_offset
5692 // bitmask: One bit for each register used.
5693 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
5694 // first register is expected to be saved.
5695 // Examples:
5696 // .mask 0x80000000, -4
5697 // .fmask 0x80000000, -4
5698 //
Jack Carterbe332172012-09-07 00:48:02 +00005699
Daniel Sandersd97a6342014-08-13 10:07:34 +00005700 // Parse the bitmask
5701 const MCExpr *BitMask;
5702 int64_t BitMaskVal;
5703
5704 if (Parser.parseExpression(BitMask)) {
5705 reportParseError("expected bitmask value");
5706 return false;
5707 }
5708
Jim Grosbach13760bd2015-05-30 01:25:56 +00005709 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005710 reportParseError("bitmask not an absolute expression");
5711 return false;
5712 }
5713
5714 if (Parser.getTok().is(AsmToken::Comma))
5715 Parser.Lex();
5716 else {
5717 reportParseError("unexpected token, expected comma");
5718 return false;
5719 }
5720
5721 // Parse the frame_offset
5722 const MCExpr *FrameOffset;
5723 int64_t FrameOffsetVal;
5724
5725 if (Parser.parseExpression(FrameOffset)) {
5726 reportParseError("expected frame offset value");
5727 return false;
5728 }
5729
Jim Grosbach13760bd2015-05-30 01:25:56 +00005730 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005731 reportParseError("frame offset not an absolute expression");
5732 return false;
5733 }
5734
5735 // If this is not the end of the statement, report an error.
5736 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5737 reportParseError("unexpected token, expected end of statement");
5738 return false;
5739 }
5740
5741 if (IDVal == ".mask")
5742 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
5743 else
5744 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00005745 return false;
5746 }
5747
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005748 if (IDVal == ".nan")
5749 return parseDirectiveNaN();
5750
Jack Carter07c818d2013-01-25 01:31:34 +00005751 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00005752 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00005753 return false;
5754 }
5755
Rafael Espindolab59fb732014-03-28 18:50:26 +00005756 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005757 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005758 return false;
5759 }
5760
Jack Carter07c818d2013-01-25 01:31:34 +00005761 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005762 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00005763 return false;
5764 }
5765
Jack Carter0cd3c192014-01-06 23:27:31 +00005766 if (IDVal == ".option")
5767 return parseDirectiveOption();
5768
5769 if (IDVal == ".abicalls") {
5770 getTargetStreamer().emitDirectiveAbiCalls();
5771 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005772 Error(Parser.getTok().getLoc(),
5773 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005774 // Clear line
5775 Parser.eatToEndOfStatement();
5776 }
5777 return false;
5778 }
5779
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005780 if (IDVal == ".cpsetup")
5781 return parseDirectiveCPSetup();
5782
Daniel Sandersf173dda2015-09-22 10:50:09 +00005783 if (IDVal == ".cpreturn")
5784 return parseDirectiveCPReturn();
5785
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005786 if (IDVal == ".module")
5787 return parseDirectiveModule();
5788
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00005789 if (IDVal == ".llvm_internal_mips_reallow_module_directive")
5790 return parseInternalDirectiveReallowModule();
5791
Toma Tabacu9ca50962015-04-16 09:53:47 +00005792 if (IDVal == ".insn")
5793 return parseInsnDirective();
5794
Rafael Espindola870c4e92012-01-11 03:56:41 +00005795 return true;
5796}
5797
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00005798bool MipsAsmParser::parseInternalDirectiveReallowModule() {
5799 // If this is not the end of the statement, report an error.
5800 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5801 reportParseError("unexpected token, expected end of statement");
5802 return false;
5803 }
5804
5805 getTargetStreamer().reallowModuleDirective();
5806
5807 getParser().Lex(); // Eat EndOfStatement token.
5808 return false;
5809}
5810
Rafael Espindola870c4e92012-01-11 03:56:41 +00005811extern "C" void LLVMInitializeMipsAsmParser() {
5812 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
5813 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
5814 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
5815 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
5816}
Jack Carterb4dbc172012-09-05 23:34:03 +00005817
5818#define GET_REGISTER_MATCHER
5819#define GET_MATCHER_IMPLEMENTATION
5820#include "MipsGenAsmMatcher.inc"