blob: 78c3e224a003b7dd594d4dbe3ebe0e198e57bc70 [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 {
386 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY
387#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
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000897 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000898 assert(N == 1 && "Invalid number of operands!");
899 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000900 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000901 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000902
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000903 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000904 assert(N == 2 && "Invalid number of operands!");
905
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000906 Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
907 ? getMemBase()->getGPR64Reg()
908 : getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000909
910 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000911 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000912 }
913
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000914 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
915 assert(N == 2 && "Invalid number of operands!");
916
Jim Grosbache9119e42015-05-13 18:37:00 +0000917 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000918
919 const MCExpr *Expr = getMemOff();
920 addExpr(Inst, Expr);
921 }
922
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000923 void addRegListOperands(MCInst &Inst, unsigned N) const {
924 assert(N == 1 && "Invalid number of operands!");
925
926 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000927 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000928 }
929
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000930 void addRegPairOperands(MCInst &Inst, unsigned N) const {
931 assert(N == 2 && "Invalid number of operands!");
932 unsigned RegNo = getRegPair();
Jim Grosbache9119e42015-05-13 18:37:00 +0000933 Inst.addOperand(MCOperand::createReg(RegNo++));
934 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000935 }
936
Zoran Jovanovic41688672015-02-10 16:36:20 +0000937 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
938 assert(N == 2 && "Invalid number of operands!");
939 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000940 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000941 }
942
Craig Topper56c590a2014-04-29 07:58:02 +0000943 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000944 // As a special case until we sort out the definition of div/divu, pretend
945 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
946 if (isGPRAsmReg() && RegIdx.Index == 0)
947 return true;
948
949 return Kind == k_PhysRegister;
950 }
951 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000952 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000953 bool isConstantImm() const {
954 return isImm() && dyn_cast<MCConstantExpr>(getImm());
955 }
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +0000956 template <unsigned Bits> bool isUImm() const {
957 return isImm() && isConstantImm() && isUInt<Bits>(getConstantImm());
958 }
Craig Topper56c590a2014-04-29 07:58:02 +0000959 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000960 // Note: It's not possible to pretend that other operand kinds are tokens.
961 // The matcher emitter checks tokens first.
962 return Kind == k_Token;
963 }
Craig Topper56c590a2014-04-29 07:58:02 +0000964 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000965 bool isConstantMemOff() const {
966 return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
967 }
968 template <unsigned Bits> bool isMemWithSimmOffset() const {
Zoran Jovanovica6593ff2015-08-18 12:53:08 +0000969 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
970 && getMemBase()->isGPRAsmReg();
971 }
Zoran Jovanovic6e6a2c92015-09-16 09:14:35 +0000972 template <unsigned Bits> bool isMemWithSimmOffsetGPR() const {
973 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff()) &&
974 getMemBase()->isGPRAsmReg();
975 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000976 bool isMemWithGRPMM16Base() const {
977 return isMem() && getMemBase()->isMM16AsmReg();
978 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000979 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
980 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
981 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
982 }
Jozef Kolek12c69822014-12-23 16:16:33 +0000983 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
984 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
985 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
986 && (getMemBase()->getGPR32Reg() == Mips::SP);
987 }
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +0000988 bool isUImm5Lsl2() const {
989 return (isImm() && isConstantImm() && isShiftedUInt<5, 2>(getConstantImm()));
990 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000991 bool isRegList16() const {
992 if (!isRegList())
993 return false;
994
995 int Size = RegList.List->size();
996 if (Size < 2 || Size > 5 || *RegList.List->begin() != Mips::S0 ||
997 RegList.List->back() != Mips::RA)
998 return false;
999
1000 int PrevReg = *RegList.List->begin();
1001 for (int i = 1; i < Size - 1; i++) {
1002 int Reg = (*(RegList.List))[i];
1003 if ( Reg != PrevReg + 1)
1004 return false;
1005 PrevReg = Reg;
1006 }
1007
1008 return true;
1009 }
Vladimir Medic2b953d02013-10-01 09:48:56 +00001010 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001011 bool isLSAImm() const {
1012 if (!isConstantImm())
1013 return false;
1014 int64_t Val = getConstantImm();
1015 return 1 <= Val && Val <= 4;
1016 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001017 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001018 bool isMovePRegPair() const {
1019 if (Kind != k_RegList || RegList.List->size() != 2)
1020 return false;
1021
1022 unsigned R0 = RegList.List->front();
1023 unsigned R1 = RegList.List->back();
1024
1025 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
1026 (R0 == Mips::A1 && R1 == Mips::A3) ||
1027 (R0 == Mips::A2 && R1 == Mips::A3) ||
1028 (R0 == Mips::A0 && R1 == Mips::S5) ||
1029 (R0 == Mips::A0 && R1 == Mips::S6) ||
1030 (R0 == Mips::A0 && R1 == Mips::A1) ||
1031 (R0 == Mips::A0 && R1 == Mips::A2) ||
1032 (R0 == Mips::A0 && R1 == Mips::A3))
1033 return true;
1034
1035 return false;
1036 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001037
1038 StringRef getToken() const {
1039 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001040 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001041 }
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001042 bool isRegPair() const { return Kind == k_RegPair; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001043
Craig Topper56c590a2014-04-29 07:58:02 +00001044 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001045 // As a special case until we sort out the definition of div/divu, pretend
1046 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
1047 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1048 RegIdx.Kind & RegKind_GPR)
1049 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001050
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001051 assert(Kind == k_PhysRegister && "Invalid access!");
1052 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +00001053 }
1054
Jack Carterb4dbc172012-09-05 23:34:03 +00001055 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001056 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001057 return Imm.Val;
1058 }
1059
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001060 int64_t getConstantImm() const {
1061 const MCExpr *Val = getImm();
1062 return static_cast<const MCConstantExpr *>(Val)->getValue();
1063 }
1064
1065 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001066 assert((Kind == k_Memory) && "Invalid access!");
1067 return Mem.Base;
1068 }
1069
1070 const MCExpr *getMemOff() const {
1071 assert((Kind == k_Memory) && "Invalid access!");
1072 return Mem.Off;
1073 }
1074
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001075 int64_t getConstantMemOff() const {
1076 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1077 }
1078
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001079 const SmallVectorImpl<unsigned> &getRegList() const {
1080 assert((Kind == k_RegList) && "Invalid access!");
1081 return *(RegList.List);
1082 }
1083
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001084 unsigned getRegPair() const {
1085 assert((Kind == k_RegPair) && "Invalid access!");
1086 return RegIdx.Index;
1087 }
1088
David Blaikie960ea3f2014-06-08 16:18:35 +00001089 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1090 MipsAsmParser &Parser) {
1091 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001092 Op->Tok.Data = Str.data();
1093 Op->Tok.Length = Str.size();
1094 Op->StartLoc = S;
1095 Op->EndLoc = S;
1096 return Op;
1097 }
1098
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001099 /// Create a numeric register (e.g. $1). The exact register remains
1100 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001101 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001102 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001103 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001104 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001105 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001106 }
1107
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001108 /// Create a register that is definitely a GPR.
1109 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001110 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001111 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001112 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001113 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001114 }
1115
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001116 /// Create a register that is definitely a FGR.
1117 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001118 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001119 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001120 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001121 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
1122 }
1123
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001124 /// Create a register that is definitely a HWReg.
1125 /// This is typically only used for named registers such as $hwr_cpunum.
1126 static std::unique_ptr<MipsOperand>
1127 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
1128 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1129 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
1130 }
1131
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001132 /// Create a register that is definitely an FCC.
1133 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001134 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001135 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001136 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001137 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
1138 }
1139
1140 /// Create a register that is definitely an ACC.
1141 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001142 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001143 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001144 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001145 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
1146 }
1147
1148 /// Create a register that is definitely an MSA128.
1149 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001150 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001151 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001152 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001153 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
1154 }
1155
1156 /// Create a register that is definitely an MSACtrl.
1157 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001158 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001159 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001160 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001161 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
1162 }
1163
David Blaikie960ea3f2014-06-08 16:18:35 +00001164 static std::unique_ptr<MipsOperand>
1165 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1166 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001167 Op->Imm.Val = Val;
1168 Op->StartLoc = S;
1169 Op->EndLoc = E;
1170 return Op;
1171 }
1172
David Blaikie960ea3f2014-06-08 16:18:35 +00001173 static std::unique_ptr<MipsOperand>
1174 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1175 SMLoc E, MipsAsmParser &Parser) {
1176 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1177 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001178 Op->Mem.Off = Off;
1179 Op->StartLoc = S;
1180 Op->EndLoc = E;
1181 return Op;
1182 }
1183
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001184 static std::unique_ptr<MipsOperand>
1185 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1186 MipsAsmParser &Parser) {
1187 assert (Regs.size() > 0 && "Empty list not allowed");
1188
1189 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001190 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001191 Op->StartLoc = StartLoc;
1192 Op->EndLoc = EndLoc;
1193 return Op;
1194 }
1195
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001196 static std::unique_ptr<MipsOperand>
1197 CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1198 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
1199 Op->RegIdx.Index = RegNo;
1200 Op->StartLoc = S;
1201 Op->EndLoc = E;
1202 return Op;
1203 }
1204
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001205 bool isGPRAsmReg() const {
1206 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001207 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001208 bool isMM16AsmReg() const {
1209 if (!(isRegIdx() && RegIdx.Kind))
1210 return false;
1211 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1212 || RegIdx.Index == 16 || RegIdx.Index == 17);
1213 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001214 bool isMM16AsmRegZero() const {
1215 if (!(isRegIdx() && RegIdx.Kind))
1216 return false;
1217 return (RegIdx.Index == 0 ||
1218 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1219 RegIdx.Index == 17);
1220 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001221 bool isMM16AsmRegMoveP() const {
1222 if (!(isRegIdx() && RegIdx.Kind))
1223 return false;
1224 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1225 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1226 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001227 bool isFGRAsmReg() const {
1228 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1229 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001230 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001231 bool isHWRegsAsmReg() const {
1232 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001233 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001234 bool isCCRAsmReg() const {
1235 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001236 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001237 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001238 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1239 return false;
1240 if (!AsmParser.hasEightFccRegisters())
1241 return RegIdx.Index == 0;
1242 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001243 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001244 bool isACCAsmReg() const {
1245 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001246 }
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001247 bool isCOP0AsmReg() const {
1248 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1249 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001250 bool isCOP2AsmReg() const {
1251 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001252 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001253 bool isCOP3AsmReg() const {
1254 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1255 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001256 bool isMSA128AsmReg() const {
1257 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001258 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001259 bool isMSACtrlAsmReg() const {
1260 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001261 }
1262
Jack Carterb4dbc172012-09-05 23:34:03 +00001263 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001264 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001265 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001266 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001267
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001268 virtual ~MipsOperand() {
1269 switch (Kind) {
1270 case k_Immediate:
1271 break;
1272 case k_Memory:
1273 delete Mem.Base;
1274 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001275 case k_RegList:
1276 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001277 case k_PhysRegister:
1278 case k_RegisterIndex:
1279 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001280 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001281 break;
1282 }
1283 }
1284
Craig Topper56c590a2014-04-29 07:58:02 +00001285 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001286 switch (Kind) {
1287 case k_Immediate:
1288 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001289 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001290 OS << ">";
1291 break;
1292 case k_Memory:
1293 OS << "Mem<";
1294 Mem.Base->print(OS);
1295 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001296 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001297 OS << ">";
1298 break;
1299 case k_PhysRegister:
1300 OS << "PhysReg<" << PhysReg.Num << ">";
1301 break;
1302 case k_RegisterIndex:
1303 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1304 break;
1305 case k_Token:
1306 OS << Tok.Data;
1307 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001308 case k_RegList:
1309 OS << "RegList< ";
1310 for (auto Reg : (*RegList.List))
1311 OS << Reg << " ";
1312 OS << ">";
1313 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001314 case k_RegPair:
1315 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1316 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001317 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001318 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001319}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001320} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001321
Jack Carter9e65aa32013-03-22 00:05:30 +00001322namespace llvm {
1323extern const MCInstrDesc MipsInsts[];
1324}
1325static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1326 return MipsInsts[Opcode];
1327}
1328
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001329static bool hasShortDelaySlot(unsigned Opcode) {
1330 switch (Opcode) {
1331 case Mips::JALS_MM:
1332 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001333 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001334 case Mips::BGEZALS_MM:
1335 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001336 return true;
1337 default:
1338 return false;
1339 }
1340}
1341
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001342static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1343 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1344 return &SRExpr->getSymbol();
1345 }
1346
1347 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1348 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1349 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1350
1351 if (LHSSym)
1352 return LHSSym;
1353
1354 if (RHSSym)
1355 return RHSSym;
1356
1357 return nullptr;
1358 }
1359
1360 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1361 return getSingleMCSymbol(UExpr->getSubExpr());
1362
1363 return nullptr;
1364}
1365
1366static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1367 if (isa<MCSymbolRefExpr>(Expr))
1368 return 1;
1369
1370 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1371 return countMCSymbolRefExpr(BExpr->getLHS()) +
1372 countMCSymbolRefExpr(BExpr->getRHS());
1373
1374 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1375 return countMCSymbolRefExpr(UExpr->getSubExpr());
1376
1377 return 0;
1378}
1379
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001380namespace {
1381void emitRX(unsigned Opcode, unsigned Reg0, MCOperand Op1, SMLoc IDLoc,
1382 SmallVectorImpl<MCInst> &Instructions) {
1383 MCInst tmpInst;
1384 tmpInst.setOpcode(Opcode);
1385 tmpInst.addOperand(MCOperand::createReg(Reg0));
1386 tmpInst.addOperand(Op1);
1387 tmpInst.setLoc(IDLoc);
1388 Instructions.push_back(tmpInst);
1389}
1390
1391void emitRI(unsigned Opcode, unsigned Reg0, int32_t Imm, SMLoc IDLoc,
1392 SmallVectorImpl<MCInst> &Instructions) {
1393 emitRX(Opcode, Reg0, MCOperand::createImm(Imm), IDLoc, Instructions);
1394}
1395
1396void emitRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, SMLoc IDLoc,
1397 SmallVectorImpl<MCInst> &Instructions) {
1398 emitRX(Opcode, Reg0, MCOperand::createReg(Reg1), IDLoc, Instructions);
1399}
1400
1401void emitII(unsigned Opcode, int16_t Imm1, int16_t Imm2, SMLoc IDLoc,
1402 SmallVectorImpl<MCInst> &Instructions) {
1403 MCInst tmpInst;
1404 tmpInst.setOpcode(Opcode);
1405 tmpInst.addOperand(MCOperand::createImm(Imm1));
1406 tmpInst.addOperand(MCOperand::createImm(Imm2));
1407 tmpInst.setLoc(IDLoc);
1408 Instructions.push_back(tmpInst);
1409}
1410
1411void emitR(unsigned Opcode, unsigned Reg0, SMLoc IDLoc,
1412 SmallVectorImpl<MCInst> &Instructions) {
1413 MCInst tmpInst;
1414 tmpInst.setOpcode(Opcode);
1415 tmpInst.addOperand(MCOperand::createReg(Reg0));
1416 tmpInst.setLoc(IDLoc);
1417 Instructions.push_back(tmpInst);
1418}
1419
1420void emitRRX(unsigned Opcode, unsigned Reg0, unsigned Reg1, MCOperand Op2,
1421 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1422 MCInst tmpInst;
1423 tmpInst.setOpcode(Opcode);
1424 tmpInst.addOperand(MCOperand::createReg(Reg0));
1425 tmpInst.addOperand(MCOperand::createReg(Reg1));
1426 tmpInst.addOperand(Op2);
1427 tmpInst.setLoc(IDLoc);
1428 Instructions.push_back(tmpInst);
1429}
1430
1431void emitRRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, unsigned Reg2,
1432 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1433 emitRRX(Opcode, Reg0, Reg1, MCOperand::createReg(Reg2), IDLoc,
1434 Instructions);
1435}
1436
1437void emitRRI(unsigned Opcode, unsigned Reg0, unsigned Reg1, int16_t Imm,
1438 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1439 emitRRX(Opcode, Reg0, Reg1, MCOperand::createImm(Imm), IDLoc,
1440 Instructions);
1441}
1442
1443void emitAppropriateDSLL(unsigned DstReg, unsigned SrcReg, int16_t ShiftAmount,
1444 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1445 if (ShiftAmount >= 32) {
1446 emitRRI(Mips::DSLL32, DstReg, SrcReg, ShiftAmount - 32, IDLoc,
1447 Instructions);
1448 return;
1449 }
1450
1451 emitRRI(Mips::DSLL, DstReg, SrcReg, ShiftAmount, IDLoc, Instructions);
1452}
1453} // end anonymous namespace.
1454
Jack Carter9e65aa32013-03-22 00:05:30 +00001455bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001456 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001457 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001458 bool ExpandedJalSym = false;
Daniel Sandersa771fef2014-03-24 14:05:39 +00001459
Jack Carter9e65aa32013-03-22 00:05:30 +00001460 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001461
1462 if (MCID.isBranch() || MCID.isCall()) {
1463 const unsigned Opcode = Inst.getOpcode();
1464 MCOperand Offset;
1465
1466 switch (Opcode) {
1467 default:
1468 break;
Kai Nackee0245392015-01-27 19:11:28 +00001469 case Mips::BBIT0:
1470 case Mips::BBIT032:
1471 case Mips::BBIT1:
1472 case Mips::BBIT132:
1473 assert(hasCnMips() && "instruction only valid for octeon cpus");
1474 // Fall through
1475
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001476 case Mips::BEQ:
1477 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001478 case Mips::BEQ_MM:
1479 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001480 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001481 Offset = Inst.getOperand(2);
1482 if (!Offset.isImm())
1483 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001484 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001485 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001486 if (OffsetToAlignment(Offset.getImm(),
1487 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001488 return Error(IDLoc, "branch to misaligned address");
1489 break;
1490 case Mips::BGEZ:
1491 case Mips::BGTZ:
1492 case Mips::BLEZ:
1493 case Mips::BLTZ:
1494 case Mips::BGEZAL:
1495 case Mips::BLTZAL:
1496 case Mips::BC1F:
1497 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001498 case Mips::BGEZ_MM:
1499 case Mips::BGTZ_MM:
1500 case Mips::BLEZ_MM:
1501 case Mips::BLTZ_MM:
1502 case Mips::BGEZAL_MM:
1503 case Mips::BLTZAL_MM:
1504 case Mips::BC1F_MM:
1505 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001506 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001507 Offset = Inst.getOperand(1);
1508 if (!Offset.isImm())
1509 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001510 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001511 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001512 if (OffsetToAlignment(Offset.getImm(),
1513 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001514 return Error(IDLoc, "branch to misaligned address");
1515 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001516 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001517 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001518 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001519 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001520 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1521 Offset = Inst.getOperand(1);
1522 if (!Offset.isImm())
1523 break; // We'll deal with this situation later on when applying fixups.
Craig Topper55b1f292015-10-10 20:17:07 +00001524 if (!isInt<8>(Offset.getImm()))
Jozef Kolek9761e962015-01-12 12:03:34 +00001525 return Error(IDLoc, "branch target out of range");
1526 if (OffsetToAlignment(Offset.getImm(), 2LL))
1527 return Error(IDLoc, "branch to misaligned address");
1528 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001529 }
1530 }
1531
Daniel Sandersa84989a2014-06-16 13:25:35 +00001532 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1533 // We still accept it but it is a normal nop.
1534 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1535 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1536 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1537 "nop instruction");
1538 }
1539
Kai Nackee0245392015-01-27 19:11:28 +00001540 if (hasCnMips()) {
1541 const unsigned Opcode = Inst.getOpcode();
1542 MCOperand Opnd;
1543 int Imm;
1544
1545 switch (Opcode) {
1546 default:
1547 break;
1548
1549 case Mips::BBIT0:
1550 case Mips::BBIT032:
1551 case Mips::BBIT1:
1552 case Mips::BBIT132:
1553 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1554 // The offset is handled above
1555 Opnd = Inst.getOperand(1);
1556 if (!Opnd.isImm())
1557 return Error(IDLoc, "expected immediate operand kind");
1558 Imm = Opnd.getImm();
1559 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1560 Opcode == Mips::BBIT1 ? 63 : 31))
1561 return Error(IDLoc, "immediate operand value out of range");
1562 if (Imm > 31) {
1563 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1564 : Mips::BBIT132);
1565 Inst.getOperand(1).setImm(Imm - 32);
1566 }
1567 break;
1568
1569 case Mips::CINS:
1570 case Mips::CINS32:
1571 case Mips::EXTS:
1572 case Mips::EXTS32:
1573 assert(MCID.getNumOperands() == 4 && "unexpected number of operands");
1574 // Check length
1575 Opnd = Inst.getOperand(3);
1576 if (!Opnd.isImm())
1577 return Error(IDLoc, "expected immediate operand kind");
1578 Imm = Opnd.getImm();
1579 if (Imm < 0 || Imm > 31)
1580 return Error(IDLoc, "immediate operand value out of range");
1581 // Check position
1582 Opnd = Inst.getOperand(2);
1583 if (!Opnd.isImm())
1584 return Error(IDLoc, "expected immediate operand kind");
1585 Imm = Opnd.getImm();
1586 if (Imm < 0 || Imm > (Opcode == Mips::CINS ||
1587 Opcode == Mips::EXTS ? 63 : 31))
1588 return Error(IDLoc, "immediate operand value out of range");
1589 if (Imm > 31) {
1590 Inst.setOpcode(Opcode == Mips::CINS ? Mips::CINS32 : Mips::EXTS32);
1591 Inst.getOperand(2).setImm(Imm - 32);
1592 }
1593 break;
1594
1595 case Mips::SEQi:
1596 case Mips::SNEi:
1597 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1598 Opnd = Inst.getOperand(2);
1599 if (!Opnd.isImm())
1600 return Error(IDLoc, "expected immediate operand kind");
1601 Imm = Opnd.getImm();
1602 if (!isInt<10>(Imm))
1603 return Error(IDLoc, "immediate operand value out of range");
1604 break;
1605 }
1606 }
1607
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001608 // This expansion is not in a function called by tryExpandInstruction()
1609 // because the pseudo-instruction doesn't have a distinct opcode.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001610 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
1611 inPicMode()) {
1612 warnIfNoMacro(IDLoc);
1613
1614 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
1615
1616 // We can do this expansion if there's only 1 symbol in the argument
1617 // expression.
1618 if (countMCSymbolRefExpr(JalExpr) > 1)
1619 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
1620
1621 // FIXME: This is checking the expression can be handled by the later stages
1622 // of the assembler. We ought to leave it to those later stages but
1623 // we can't do that until we stop evaluateRelocExpr() rewriting the
1624 // expressions into non-equivalent forms.
1625 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
1626
1627 // FIXME: Add support for label+offset operands (currently causes an error).
1628 // FIXME: Add support for forward-declared local symbols.
1629 // FIXME: Add expansion for when the LargeGOT option is enabled.
1630 if (JalSym->isInSection() || JalSym->isTemporary()) {
1631 if (isABI_O32()) {
1632 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001633 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001634 // R_(MICRO)MIPS_GOT16 label
1635 // addiu $25, $25, 0
1636 // R_(MICRO)MIPS_LO16 label
1637 // jalr $25
1638 const MCExpr *Got16RelocExpr = evaluateRelocExpr(JalExpr, "got");
1639 const MCExpr *Lo16RelocExpr = evaluateRelocExpr(JalExpr, "lo");
1640
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001641 emitRRX(Mips::LW, Mips::T9, Mips::GP,
1642 MCOperand::createExpr(Got16RelocExpr), IDLoc, Instructions);
1643 emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
1644 MCOperand::createExpr(Lo16RelocExpr), IDLoc, Instructions);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001645 } else if (isABI_N32() || isABI_N64()) {
1646 // If it's a local symbol and the N32/N64 ABIs are being used,
1647 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001648 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001649 // R_(MICRO)MIPS_GOT_DISP label
1650 // jalr $25
1651 const MCExpr *GotDispRelocExpr = evaluateRelocExpr(JalExpr, "got_disp");
1652
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001653 emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
1654 MCOperand::createExpr(GotDispRelocExpr), IDLoc, Instructions);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001655 }
1656 } else {
1657 // If it's an external/weak symbol, we expand to:
1658 // lw/ld $25, 0($gp)
1659 // R_(MICRO)MIPS_CALL16 label
1660 // jalr $25
1661 const MCExpr *Call16RelocExpr = evaluateRelocExpr(JalExpr, "call16");
1662
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001663 emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
1664 MCOperand::createExpr(Call16RelocExpr), IDLoc, Instructions);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001665 }
1666
1667 MCInst JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001668 if (IsCpRestoreSet && inMicroMipsMode())
1669 JalrInst.setOpcode(Mips::JALRS_MM);
1670 else
1671 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001672 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
1673 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
1674
1675 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
1676 // This relocation is supposed to be an optimization hint for the linker
1677 // and is not necessary for correctness.
1678
1679 Inst = JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001680 ExpandedJalSym = true;
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001681 }
1682
Jack Carter9e65aa32013-03-22 00:05:30 +00001683 if (MCID.mayLoad() || MCID.mayStore()) {
1684 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001685 // reference or immediate we may have to expand instructions.
1686 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001687 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001688 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1689 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001690 MCOperand &Op = Inst.getOperand(i);
1691 if (Op.isImm()) {
1692 int MemOffset = Op.getImm();
1693 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001694 // Offset can't exceed 16bit value.
1695 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001696 return false;
1697 }
1698 } else if (Op.isExpr()) {
1699 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001700 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001701 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001702 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001703 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001704 // Expand symbol.
1705 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001706 return false;
1707 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001708 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001709 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001710 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001711 }
1712 }
1713 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001714 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001715 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001716
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001717 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001718 if (MCID.mayLoad()) {
1719 // Try to create 16-bit GP relative load instruction.
1720 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1721 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1722 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1723 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1724 MCOperand &Op = Inst.getOperand(i);
1725 if (Op.isImm()) {
1726 int MemOffset = Op.getImm();
1727 MCOperand &DstReg = Inst.getOperand(0);
1728 MCOperand &BaseReg = Inst.getOperand(1);
Craig Topper55b1f292015-10-10 20:17:07 +00001729 if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&
Jozef Koleke10a02e2015-01-28 17:27:26 +00001730 getContext().getRegisterInfo()->getRegClass(
1731 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00001732 (BaseReg.getReg() == Mips::GP ||
1733 BaseReg.getReg() == Mips::GP_64)) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001734
1735 emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
1736 IDLoc, Instructions);
Jozef Koleke10a02e2015-01-28 17:27:26 +00001737 return false;
1738 }
1739 }
1740 }
1741 } // for
1742 } // if load
1743
1744 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1745
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001746 MCOperand Opnd;
1747 int Imm;
1748
1749 switch (Inst.getOpcode()) {
1750 default:
1751 break;
1752 case Mips::ADDIUS5_MM:
1753 Opnd = Inst.getOperand(2);
1754 if (!Opnd.isImm())
1755 return Error(IDLoc, "expected immediate operand kind");
1756 Imm = Opnd.getImm();
1757 if (Imm < -8 || Imm > 7)
1758 return Error(IDLoc, "immediate operand value out of range");
1759 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001760 case Mips::ADDIUSP_MM:
1761 Opnd = Inst.getOperand(0);
1762 if (!Opnd.isImm())
1763 return Error(IDLoc, "expected immediate operand kind");
1764 Imm = Opnd.getImm();
1765 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1766 Imm % 4 != 0)
1767 return Error(IDLoc, "immediate operand value out of range");
1768 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001769 case Mips::SLL16_MM:
1770 case Mips::SRL16_MM:
1771 Opnd = Inst.getOperand(2);
1772 if (!Opnd.isImm())
1773 return Error(IDLoc, "expected immediate operand kind");
1774 Imm = Opnd.getImm();
1775 if (Imm < 1 || Imm > 8)
1776 return Error(IDLoc, "immediate operand value out of range");
1777 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001778 case Mips::LI16_MM:
1779 Opnd = Inst.getOperand(1);
1780 if (!Opnd.isImm())
1781 return Error(IDLoc, "expected immediate operand kind");
1782 Imm = Opnd.getImm();
1783 if (Imm < -1 || Imm > 126)
1784 return Error(IDLoc, "immediate operand value out of range");
1785 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001786 case Mips::ADDIUR2_MM:
1787 Opnd = Inst.getOperand(2);
1788 if (!Opnd.isImm())
1789 return Error(IDLoc, "expected immediate operand kind");
1790 Imm = Opnd.getImm();
1791 if (!(Imm == 1 || Imm == -1 ||
1792 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1793 return Error(IDLoc, "immediate operand value out of range");
1794 break;
Zoran Jovanovic42b84442014-10-23 11:13:59 +00001795 case Mips::ADDIUR1SP_MM:
1796 Opnd = Inst.getOperand(1);
1797 if (!Opnd.isImm())
1798 return Error(IDLoc, "expected immediate operand kind");
1799 Imm = Opnd.getImm();
1800 if (OffsetToAlignment(Imm, 4LL))
1801 return Error(IDLoc, "misaligned immediate operand value");
1802 if (Imm < 0 || Imm > 255)
1803 return Error(IDLoc, "immediate operand value out of range");
1804 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001805 case Mips::ANDI16_MM:
1806 Opnd = Inst.getOperand(2);
1807 if (!Opnd.isImm())
1808 return Error(IDLoc, "expected immediate operand kind");
1809 Imm = Opnd.getImm();
1810 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1811 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1812 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1813 return Error(IDLoc, "immediate operand value out of range");
1814 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001815 case Mips::LBU16_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 < -1 || Imm > 14)
1821 return Error(IDLoc, "immediate operand value out of range");
1822 break;
Zoran Jovanovic7ba636c2015-09-17 10:14:09 +00001823 case Mips::TEQ_MM:
1824 case Mips::TGE_MM:
1825 case Mips::TGEU_MM:
1826 case Mips::TLT_MM:
1827 case Mips::TLTU_MM:
1828 case Mips::TNE_MM:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001829 case Mips::SB16_MM:
1830 Opnd = Inst.getOperand(2);
1831 if (!Opnd.isImm())
1832 return Error(IDLoc, "expected immediate operand kind");
1833 Imm = Opnd.getImm();
1834 if (Imm < 0 || Imm > 15)
1835 return Error(IDLoc, "immediate operand value out of range");
1836 break;
1837 case Mips::LHU16_MM:
1838 case Mips::SH16_MM:
1839 Opnd = Inst.getOperand(2);
1840 if (!Opnd.isImm())
1841 return Error(IDLoc, "expected immediate operand kind");
1842 Imm = Opnd.getImm();
1843 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1844 return Error(IDLoc, "immediate operand value out of range");
1845 break;
1846 case Mips::LW16_MM:
1847 case Mips::SW16_MM:
1848 Opnd = Inst.getOperand(2);
1849 if (!Opnd.isImm())
1850 return Error(IDLoc, "expected immediate operand kind");
1851 Imm = Opnd.getImm();
1852 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1853 return Error(IDLoc, "immediate operand value out of range");
1854 break;
Zoran Jovanovic6e6a2c92015-09-16 09:14:35 +00001855 case Mips::PREFX_MM:
Jozef Kolekab6d1cc2014-12-23 19:55:34 +00001856 case Mips::CACHE:
1857 case Mips::PREF:
1858 Opnd = Inst.getOperand(2);
1859 if (!Opnd.isImm())
1860 return Error(IDLoc, "expected immediate operand kind");
1861 Imm = Opnd.getImm();
1862 if (!isUInt<5>(Imm))
1863 return Error(IDLoc, "immediate operand value out of range");
1864 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001865 case Mips::ADDIUPC_MM:
1866 MCOperand Opnd = Inst.getOperand(1);
1867 if (!Opnd.isImm())
1868 return Error(IDLoc, "expected immediate operand kind");
1869 int Imm = Opnd.getImm();
Craig Topper55b1f292015-10-10 20:17:07 +00001870 if ((Imm % 4 != 0) || !isInt<25>(Imm))
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001871 return Error(IDLoc, "immediate operand value out of range");
1872 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001873 }
1874 }
1875
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001876 MacroExpanderResultTy ExpandResult =
1877 tryExpandInstruction(Inst, IDLoc, Instructions);
1878 switch (ExpandResult) {
1879 case MER_NotAMacro:
Jack Carter9e65aa32013-03-22 00:05:30 +00001880 Instructions.push_back(Inst);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001881 break;
1882 case MER_Success:
1883 break;
1884 case MER_Fail:
1885 return true;
1886 }
Jack Carter9e65aa32013-03-22 00:05:30 +00001887
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001888 // If this instruction has a delay slot and .set reorder is active,
1889 // emit a NOP after it.
1890 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
1891 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1892
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001893 if ((Inst.getOpcode() == Mips::JalOneReg ||
1894 Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
1895 isPicAndNotNxxAbi()) {
1896 if (IsCpRestoreSet) {
1897 // We need a NOP between the JALR and the LW:
1898 // If .set reorder has been used, we've already emitted a NOP.
1899 // If .set noreorder has been used, we need to emit a NOP at this point.
1900 if (!AssemblerOptions.back()->isReorder())
1901 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1902
1903 // Load the $gp from the stack.
1904 SmallVector<MCInst, 3> LoadInsts;
1905 createCpRestoreMemOp(true /*IsLoad*/, CpRestoreOffset /*StackOffset*/,
1906 IDLoc, LoadInsts);
1907
1908 for (const MCInst &Inst : LoadInsts)
1909 Instructions.push_back(Inst);
1910
1911 } else
1912 Warning(IDLoc, "no .cprestore used in PIC mode");
1913 }
1914
Jack Carter9e65aa32013-03-22 00:05:30 +00001915 return false;
1916}
1917
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001918MipsAsmParser::MacroExpanderResultTy
1919MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
1920 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001921 switch (Inst.getOpcode()) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001922 default:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001923 return MER_NotAMacro;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001924 case Mips::LoadImm32:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001925 return expandLoadImm(Inst, true, IDLoc, Instructions) ? MER_Fail
1926 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001927 case Mips::LoadImm64:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001928 return expandLoadImm(Inst, false, IDLoc, Instructions) ? MER_Fail
1929 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001930 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001931 case Mips::LoadAddrImm64:
1932 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1933 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
1934 "expected immediate operand kind");
1935
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001936 return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,
1937 Inst.getOperand(1),
1938 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,
1939 Instructions)
1940 ? MER_Fail
1941 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001942 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001943 case Mips::LoadAddrReg64:
1944 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1945 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1946 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
1947 "expected immediate operand kind");
1948
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001949 return expandLoadAddress(Inst.getOperand(0).getReg(),
1950 Inst.getOperand(1).getReg(), Inst.getOperand(2),
1951 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,
1952 Instructions)
1953 ? MER_Fail
1954 : MER_Success;
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001955 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001956 case Mips::B_MMR6_Pseudo:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001957 return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions) ? MER_Fail
1958 : MER_Success;
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001959 case Mips::SWM_MM:
1960 case Mips::LWM_MM:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001961 return expandLoadStoreMultiple(Inst, IDLoc, Instructions) ? MER_Fail
1962 : MER_Success;
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001963 case Mips::JalOneReg:
1964 case Mips::JalTwoReg:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001965 return expandJalWithRegs(Inst, IDLoc, Instructions) ? MER_Fail
1966 : MER_Success;
Toma Tabacue1e460d2015-06-11 10:36:10 +00001967 case Mips::BneImm:
1968 case Mips::BeqImm:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001969 return expandBranchImm(Inst, IDLoc, Instructions) ? MER_Fail : MER_Success;
Toma Tabacu1a108322015-06-17 13:20:24 +00001970 case Mips::BLT:
1971 case Mips::BLE:
1972 case Mips::BGE:
1973 case Mips::BGT:
1974 case Mips::BLTU:
1975 case Mips::BLEU:
1976 case Mips::BGEU:
1977 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00001978 case Mips::BLTL:
1979 case Mips::BLEL:
1980 case Mips::BGEL:
1981 case Mips::BGTL:
1982 case Mips::BLTUL:
1983 case Mips::BLEUL:
1984 case Mips::BGEUL:
1985 case Mips::BGTUL:
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00001986 case Mips::BLTImmMacro:
1987 case Mips::BLEImmMacro:
1988 case Mips::BGEImmMacro:
1989 case Mips::BGTImmMacro:
1990 case Mips::BLTUImmMacro:
1991 case Mips::BLEUImmMacro:
1992 case Mips::BGEUImmMacro:
1993 case Mips::BGTUImmMacro:
1994 case Mips::BLTLImmMacro:
1995 case Mips::BLELImmMacro:
1996 case Mips::BGELImmMacro:
1997 case Mips::BGTLImmMacro:
1998 case Mips::BLTULImmMacro:
1999 case Mips::BLEULImmMacro:
2000 case Mips::BGEULImmMacro:
2001 case Mips::BGTULImmMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002002 return expandCondBranches(Inst, IDLoc, Instructions) ? MER_Fail
2003 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002004 case Mips::SDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002005 return expandDiv(Inst, IDLoc, Instructions, false, true) ? MER_Fail
2006 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002007 case Mips::DSDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002008 return expandDiv(Inst, IDLoc, Instructions, true, true) ? MER_Fail
2009 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002010 case Mips::UDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002011 return expandDiv(Inst, IDLoc, Instructions, false, false) ? MER_Fail
2012 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002013 case Mips::DUDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002014 return expandDiv(Inst, IDLoc, Instructions, true, false) ? MER_Fail
2015 : MER_Success;
Daniel Sanders6394ee52015-10-15 14:52:58 +00002016 case Mips::Ulh:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002017 return expandUlh(Inst, true, IDLoc, Instructions) ? MER_Fail : MER_Success;
Toma Tabacud88d79c2015-06-23 14:39:42 +00002018 case Mips::Ulhu:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002019 return expandUlh(Inst, false, IDLoc, Instructions) ? MER_Fail : MER_Success;
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00002020 case Mips::Ulw:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002021 return expandUlw(Inst, IDLoc, Instructions) ? MER_Fail : MER_Success;
2022 case Mips::NORImm:
2023 return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail
2024 : MER_Success;
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002025 case Mips::ADDi:
2026 case Mips::ADDiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002027 case Mips::SLTi:
2028 case Mips::SLTiu:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002029 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2030 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2031 int64_t ImmValue = Inst.getOperand(2).getImm();
2032 if (isInt<16>(ImmValue))
2033 return MER_NotAMacro;
2034 return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail
2035 : MER_Success;
2036 }
2037 return MER_NotAMacro;
2038 case Mips::ANDi:
2039 case Mips::ORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002040 case Mips::XORi:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002041 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2042 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2043 int64_t ImmValue = Inst.getOperand(2).getImm();
2044 if (isUInt<16>(ImmValue))
2045 return MER_NotAMacro;
2046 return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail
2047 : MER_Success;
2048 }
2049 return MER_NotAMacro;
Jack Carterd0bd6422013-04-18 00:41:53 +00002050 }
Jack Carter30a59822012-10-04 04:03:53 +00002051}
Jack Carter92995f12012-10-06 00:53:28 +00002052
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002053bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
2054 SmallVectorImpl<MCInst> &Instructions) {
2055 // Create a JALR instruction which is going to replace the pseudo-JAL.
2056 MCInst JalrInst;
2057 JalrInst.setLoc(IDLoc);
2058 const MCOperand FirstRegOp = Inst.getOperand(0);
2059 const unsigned Opcode = Inst.getOpcode();
2060
2061 if (Opcode == Mips::JalOneReg) {
2062 // jal $rs => jalr $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002063 if (IsCpRestoreSet && inMicroMipsMode()) {
2064 JalrInst.setOpcode(Mips::JALRS16_MM);
2065 JalrInst.addOperand(FirstRegOp);
2066 } else if (inMicroMipsMode()) {
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002067 JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002068 JalrInst.addOperand(FirstRegOp);
2069 } else {
2070 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002071 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002072 JalrInst.addOperand(FirstRegOp);
2073 }
2074 } else if (Opcode == Mips::JalTwoReg) {
2075 // jal $rd, $rs => jalr $rd, $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002076 if (IsCpRestoreSet && inMicroMipsMode())
2077 JalrInst.setOpcode(Mips::JALRS_MM);
2078 else
2079 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002080 JalrInst.addOperand(FirstRegOp);
2081 const MCOperand SecondRegOp = Inst.getOperand(1);
2082 JalrInst.addOperand(SecondRegOp);
2083 }
2084 Instructions.push_back(JalrInst);
2085
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002086 // If .set reorder is active and branch instruction has a delay slot,
2087 // emit a NOP after it.
2088 const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
2089 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) {
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002090 createNop(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc, Instructions);
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002091 }
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002092
2093 return false;
2094}
2095
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002096/// Can the value be represented by a unsigned N-bit value and a shift left?
Benjamin Kramer039b1042015-10-28 13:54:36 +00002097template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002098 unsigned BitNum = findFirstSet(x);
2099
2100 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2101}
2102
2103/// Load (or add) an immediate into a register.
2104///
2105/// @param ImmValue The immediate to load.
2106/// @param DstReg The register that will hold the immediate.
2107/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2108/// for a simple initialization.
2109/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2110/// @param IsAddress True if the immediate represents an address. False if it
2111/// is an integer.
2112/// @param IDLoc Location of the immediate in the source file.
2113/// @param Instructions The instructions emitted by this expansion.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002114bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002115 unsigned SrcReg, bool Is32BitImm,
2116 bool IsAddress, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00002117 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu00e98672015-05-01 12:19:27 +00002118 if (!Is32BitImm && !isGP64bit()) {
2119 Error(IDLoc, "instruction requires a 64-bit architecture");
2120 return true;
2121 }
2122
Daniel Sanders03f9c012015-07-14 12:24:22 +00002123 if (Is32BitImm) {
2124 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2125 // Sign extend up to 64-bit so that the predicates match the hardware
2126 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2127 // true.
2128 ImmValue = SignExtend64<32>(ImmValue);
2129 } else {
2130 Error(IDLoc, "instruction requires a 32-bit immediate");
2131 return true;
2132 }
2133 }
2134
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002135 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2136 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2137
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002138 bool UseSrcReg = false;
2139 if (SrcReg != Mips::NoRegister)
2140 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002141
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002142 unsigned TmpReg = DstReg;
2143 if (UseSrcReg && (DstReg == SrcReg)) {
2144 // At this point we need AT to perform the expansions and we exit if it is
2145 // not available.
2146 unsigned ATReg = getATReg(IDLoc);
2147 if (!ATReg)
2148 return true;
2149 TmpReg = ATReg;
2150 }
2151
Daniel Sanders03f9c012015-07-14 12:24:22 +00002152 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002153 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002154 SrcReg = ZeroReg;
2155
2156 // This doesn't quite follow the usual ABI expectations for N32 but matches
2157 // traditional assembler behaviour. N32 would normally use addiu for both
2158 // integers and addresses.
2159 if (IsAddress && !Is32BitImm) {
2160 emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
2161 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002162 }
2163
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002164 emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
2165 return false;
2166 }
2167
2168 if (isUInt<16>(ImmValue)) {
2169 unsigned TmpReg = DstReg;
2170 if (SrcReg == DstReg) {
2171 TmpReg = getATReg(IDLoc);
2172 if (!TmpReg)
2173 return true;
2174 }
2175
2176 emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002177 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002178 emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2179 return false;
2180 }
2181
2182 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002183 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002184
Toma Tabacu79588102015-04-29 10:19:56 +00002185 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2186 uint16_t Bits15To0 = ImmValue & 0xffff;
2187
Toma Tabacua3d056f2015-05-15 09:42:11 +00002188 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002189 // Traditional behaviour seems to special case this particular value. It's
2190 // not clear why other masks are handled differently.
2191 if (ImmValue == 0xffffffff) {
Daniel Sandersf1ae3672015-08-18 09:55:57 +00002192 emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, Instructions);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002193 emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, Instructions);
2194 if (UseSrcReg)
2195 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2196 return false;
2197 }
2198
2199 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002200 // upper 32 bits.
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002201 emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002202 emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, Instructions);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002203 if (Bits15To0)
2204 emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
2205 if (UseSrcReg)
2206 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2207 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002208 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002209
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002210 emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, Instructions);
2211 if (Bits15To0)
2212 emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002213 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002214 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2215 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002216 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002217
2218 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2219 if (Is32BitImm) {
2220 Error(IDLoc, "instruction requires a 32-bit immediate");
2221 return true;
2222 }
2223
2224 // Traditionally, these immediates are shifted as little as possible and as
2225 // such we align the most significant bit to bit 15 of our temporary.
2226 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2227 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2228 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2229 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
2230 emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, Instructions);
2231 emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, Instructions);
2232
2233 if (UseSrcReg)
2234 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2235
2236 return false;
2237 }
2238
2239 warnIfNoMacro(IDLoc);
2240
2241 // The remaining case is packed with a sequence of dsll and ori with zeros
2242 // being omitted and any neighbouring dsll's being coalesced.
2243 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2244
2245 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2246 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
2247 IDLoc, Instructions))
2248 return false;
2249
2250 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2251 // skip it and defer the shift to the next chunk.
2252 unsigned ShiftCarriedForwards = 16;
2253 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2254 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2255
2256 if (ImmChunk != 0) {
2257 emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
2258 Instructions);
2259 emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, Instructions);
2260 ShiftCarriedForwards = 0;
2261 }
2262
2263 ShiftCarriedForwards += 16;
2264 }
2265 ShiftCarriedForwards -= 16;
2266
2267 // Finish any remaining shifts left by trailing zeros.
2268 if (ShiftCarriedForwards)
2269 emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
2270 Instructions);
2271
2272 if (UseSrcReg)
2273 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2274
Matheus Almeida3813d572014-06-19 14:39:14 +00002275 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002276}
Jack Carter92995f12012-10-06 00:53:28 +00002277
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002278bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
2279 SmallVectorImpl<MCInst> &Instructions) {
2280 const MCOperand &ImmOp = Inst.getOperand(1);
2281 assert(ImmOp.isImm() && "expected immediate operand kind");
2282 const MCOperand &DstRegOp = Inst.getOperand(0);
2283 assert(DstRegOp.isReg() && "expected register operand kind");
2284
2285 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002286 Is32BitImm, false, IDLoc, Instructions))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002287 return true;
2288
2289 return false;
2290}
2291
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002292bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2293 const MCOperand &Offset,
2294 bool Is32BitAddress, SMLoc IDLoc,
2295 SmallVectorImpl<MCInst> &Instructions) {
2296 // la can't produce a usable address when addresses are 64-bit.
2297 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2298 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2299 // We currently can't do this because we depend on the equality
2300 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2301 Error(IDLoc, "la used to load 64-bit address");
2302 // Continue as if we had 'dla' instead.
2303 Is32BitAddress = false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002304 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002305
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002306 // dla requires 64-bit addresses.
2307 if (!Is32BitAddress && !ABI.ArePtrs64bit()) {
2308 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002309 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002310 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002311
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002312 if (!Offset.isImm())
2313 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
2314 Is32BitAddress, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002315
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002316 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
2317 IDLoc, Instructions);
Jack Carter543fdf82012-10-09 23:29:45 +00002318}
2319
Toma Tabacuf712ede2015-06-17 14:31:51 +00002320bool MipsAsmParser::loadAndAddSymbolAddress(
2321 const MCExpr *SymExpr, unsigned DstReg, unsigned SrcReg, bool Is32BitSym,
2322 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002323 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002324
Daniel Sandersd5a89412015-10-05 13:19:29 +00002325 const MCExpr *Symbol = cast<MCExpr>(SymExpr);
2326 const MipsMCExpr *HiExpr = MipsMCExpr::create(
2327 MCSymbolRefExpr::VK_Mips_ABS_HI, Symbol, getContext());
2328 const MipsMCExpr *LoExpr = MipsMCExpr::create(
2329 MCSymbolRefExpr::VK_Mips_ABS_LO, Symbol, getContext());
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002330
Toma Tabacufb9d1252015-06-22 12:08:39 +00002331 bool UseSrcReg = SrcReg != Mips::NoRegister;
2332
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002333 // This is the 64-bit symbol address expansion.
2334 if (ABI.ArePtrs64bit() && isGP64bit()) {
2335 // We always need AT for the 64-bit expansion.
2336 // If it is not available we exit.
2337 unsigned ATReg = getATReg(IDLoc);
2338 if (!ATReg)
2339 return true;
2340
Daniel Sandersd5a89412015-10-05 13:19:29 +00002341 const MipsMCExpr *HighestExpr = MipsMCExpr::create(
2342 MCSymbolRefExpr::VK_Mips_HIGHEST, Symbol, getContext());
2343 const MipsMCExpr *HigherExpr = MipsMCExpr::create(
2344 MCSymbolRefExpr::VK_Mips_HIGHER, Symbol, getContext());
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002345
2346 if (UseSrcReg && (DstReg == SrcReg)) {
2347 // If $rs is the same as $rd:
2348 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
2349 // daddiu $at, $at, %higher(sym)
2350 // dsll $at, $at, 16
2351 // daddiu $at, $at, %hi(sym)
2352 // dsll $at, $at, 16
2353 // daddiu $at, $at, %lo(sym)
2354 // daddu $rd, $at, $rd
2355 emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
2356 Instructions);
2357 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HigherExpr),
2358 IDLoc, Instructions);
2359 emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
2360 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
2361 Instructions);
2362 emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
2363 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
2364 Instructions);
2365 emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, Instructions);
2366
2367 return false;
2368 }
2369
2370 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2371 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
2372 // lui $at, %hi(sym)
2373 // daddiu $rd, $rd, %higher(sym)
2374 // daddiu $at, $at, %lo(sym)
2375 // dsll32 $rd, $rd, 0
2376 // daddu $rd, $rd, $at
2377 // (daddu $rd, $rd, $rs)
2378 emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
2379 Instructions);
2380 emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
2381 Instructions);
2382 emitRRX(Mips::DADDiu, DstReg, DstReg, MCOperand::createExpr(HigherExpr),
2383 IDLoc, Instructions);
2384 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
2385 Instructions);
2386 emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, Instructions);
2387 emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, Instructions);
2388 if (UseSrcReg)
2389 emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, Instructions);
2390
2391 return false;
2392 }
2393
2394 // And now, the 32-bit symbol address expansion:
2395 // If $rs is the same as $rd:
2396 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
2397 // ori $at, $at, %lo(sym)
2398 // addu $rd, $at, $rd
2399 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2400 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
2401 // ori $rd, $rd, %lo(sym)
2402 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00002403 unsigned TmpReg = DstReg;
2404 if (UseSrcReg && (DstReg == SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002405 // If $rs is the same as $rd, we need to use AT.
2406 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00002407 unsigned ATReg = getATReg(IDLoc);
2408 if (!ATReg)
2409 return true;
2410 TmpReg = ATReg;
2411 }
2412
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002413 emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, Instructions);
2414 emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr), IDLoc,
2415 Instructions);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002416
Toma Tabacufb9d1252015-06-22 12:08:39 +00002417 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002418 emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2419 else
2420 assert(DstReg == TmpReg);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002421
Toma Tabacu674825c2015-06-16 12:16:24 +00002422 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002423}
2424
NAKAMURA Takumi2bbc90c2015-01-23 01:02:07 +00002425bool MipsAsmParser::expandUncondBranchMMPseudo(
2426 MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00002427 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
2428 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002429
2430 MCOperand Offset = Inst.getOperand(0);
2431 if (Offset.isExpr()) {
2432 Inst.clear();
2433 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002434 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2435 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2436 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002437 } else {
2438 assert(Offset.isImm() && "expected immediate operand kind");
Craig Topper55b1f292015-10-10 20:17:07 +00002439 if (isInt<11>(Offset.getImm())) {
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002440 // If offset fits into 11 bits then this instruction becomes microMIPS
2441 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00002442 if (inMicroMipsMode())
2443 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002444 } else {
Craig Topper55b1f292015-10-10 20:17:07 +00002445 if (!isInt<17>(Offset.getImm()))
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002446 Error(IDLoc, "branch target out of range");
2447 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
2448 Error(IDLoc, "branch to misaligned address");
2449 Inst.clear();
2450 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002451 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2452 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2453 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002454 }
2455 }
2456 Instructions.push_back(Inst);
2457
Zoran Jovanovicada70912015-09-07 11:56:37 +00002458 // If .set reorder is active and branch instruction has a delay slot,
2459 // emit a NOP after it.
2460 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
2461 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Toma Tabacu234482a2015-03-16 12:03:39 +00002462 createNop(true, IDLoc, Instructions);
2463
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002464 return false;
2465}
2466
Toma Tabacue1e460d2015-06-11 10:36:10 +00002467bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc,
2468 SmallVectorImpl<MCInst> &Instructions) {
2469 const MCOperand &DstRegOp = Inst.getOperand(0);
2470 assert(DstRegOp.isReg() && "expected register operand kind");
2471
2472 const MCOperand &ImmOp = Inst.getOperand(1);
2473 assert(ImmOp.isImm() && "expected immediate operand kind");
2474
2475 const MCOperand &MemOffsetOp = Inst.getOperand(2);
2476 assert(MemOffsetOp.isImm() && "expected immediate operand kind");
2477
2478 unsigned OpCode = 0;
2479 switch(Inst.getOpcode()) {
2480 case Mips::BneImm:
2481 OpCode = Mips::BNE;
2482 break;
2483 case Mips::BeqImm:
2484 OpCode = Mips::BEQ;
2485 break;
2486 default:
2487 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
2488 break;
2489 }
2490
2491 int64_t ImmValue = ImmOp.getImm();
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002492 if (ImmValue == 0)
2493 emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
2494 Instructions);
2495 else {
Toma Tabacue1e460d2015-06-11 10:36:10 +00002496 warnIfNoMacro(IDLoc);
2497
2498 unsigned ATReg = getATReg(IDLoc);
2499 if (!ATReg)
2500 return true;
2501
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002502 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
2503 IDLoc, Instructions))
Toma Tabacue1e460d2015-06-11 10:36:10 +00002504 return true;
2505
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002506 emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, Instructions);
Toma Tabacue1e460d2015-06-11 10:36:10 +00002507 }
2508 return false;
2509}
2510
Jack Carter9e65aa32013-03-22 00:05:30 +00002511void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00002512 SmallVectorImpl<MCInst> &Instructions,
2513 bool isLoad, bool isImmOpnd) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002514 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00002515 const MCExpr *ExprOffset;
2516 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00002517 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002518 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2519 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002520 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002521 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2522 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002523 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00002524 if (isImmOpnd) {
2525 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
2526 ImmOffset = Inst.getOperand(2).getImm();
2527 LoOffset = ImmOffset & 0x0000ffff;
2528 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00002529 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00002530 if (LoOffset & 0x8000)
2531 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00002532 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00002533 ExprOffset = Inst.getOperand(2).getExpr();
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002534 // These are some of the types of expansions we perform here:
2535 // 1) lw $8, sym => lui $8, %hi(sym)
2536 // lw $8, %lo(sym)($8)
2537 // 2) lw $8, offset($9) => lui $8, %hi(offset)
2538 // add $8, $8, $9
2539 // lw $8, %lo(offset)($9)
2540 // 3) lw $8, offset($8) => lui $at, %hi(offset)
2541 // add $at, $at, $8
2542 // lw $8, %lo(offset)($at)
2543 // 4) sw $8, sym => lui $at, %hi(sym)
2544 // sw $8, %lo(sym)($at)
2545 // 5) sw $8, offset($8) => lui $at, %hi(offset)
2546 // add $at, $at, $8
2547 // sw $8, %lo(offset)($at)
2548 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
2549 // ldc1 $f0, %lo(sym)($at)
2550 //
2551 // For load instructions we can use the destination register as a temporary
2552 // if base and dst are different (examples 1 and 2) and if the base register
2553 // is general purpose otherwise we must use $at (example 6) and error if it's
2554 // not available. For stores we must use $at (examples 4 and 5) because we
2555 // must not clobber the source register setting up the offset.
2556 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
2557 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
2558 unsigned RegClassIDOp0 =
2559 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
2560 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
2561 (RegClassIDOp0 == Mips::GPR64RegClassID);
2562 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00002563 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002564 else {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002565 // At this point we need AT to perform the expansions and we exit if it is
2566 // not available.
Toma Tabacu89a712b2015-04-15 10:48:56 +00002567 TmpRegNum = getATReg(IDLoc);
2568 if (!TmpRegNum)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002569 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002570 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002571
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002572 emitRX(Mips::LUi, TmpRegNum,
2573 isImmOpnd ? MCOperand::createImm(HiOffset)
2574 : MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "hi")),
2575 IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00002576 // Add temp register to base.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002577 if (BaseRegNum != Mips::ZERO)
2578 emitRRR(Mips::ADDu, TmpRegNum, TmpRegNum, BaseRegNum, IDLoc, Instructions);
Alp Tokercb402912014-01-24 17:20:08 +00002579 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00002580 // of offset and new base.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002581 emitRRX(Inst.getOpcode(), RegOpNum, TmpRegNum,
2582 isImmOpnd
2583 ? MCOperand::createImm(LoOffset)
2584 : MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "lo")),
2585 IDLoc, Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +00002586}
2587
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002588bool
2589MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2590 SmallVectorImpl<MCInst> &Instructions) {
2591 unsigned OpNum = Inst.getNumOperands();
2592 unsigned Opcode = Inst.getOpcode();
2593 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2594
2595 assert (Inst.getOperand(OpNum - 1).isImm() &&
2596 Inst.getOperand(OpNum - 2).isReg() &&
2597 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2598
2599 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2600 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
2601 Inst.getOperand(OpNum - 2).getReg() == Mips::SP &&
2602 Inst.getOperand(OpNum - 3).getReg() == Mips::RA)
2603 // It can be implemented as SWM16 or LWM16 instruction.
2604 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2605
2606 Inst.setOpcode(NewOpcode);
2607 Instructions.push_back(Inst);
2608 return false;
2609}
2610
Toma Tabacu1a108322015-06-17 13:20:24 +00002611bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
2612 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002613 bool EmittedNoMacroWarning = false;
Toma Tabacu1a108322015-06-17 13:20:24 +00002614 unsigned PseudoOpcode = Inst.getOpcode();
2615 unsigned SrcReg = Inst.getOperand(0).getReg();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002616 const MCOperand &TrgOp = Inst.getOperand(1);
Toma Tabacu1a108322015-06-17 13:20:24 +00002617 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
2618
2619 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002620 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00002621
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002622 unsigned TrgReg;
2623 if (TrgOp.isReg())
2624 TrgReg = TrgOp.getReg();
2625 else if (TrgOp.isImm()) {
2626 warnIfNoMacro(IDLoc);
2627 EmittedNoMacroWarning = true;
2628
2629 TrgReg = getATReg(IDLoc);
2630 if (!TrgReg)
2631 return true;
2632
2633 switch(PseudoOpcode) {
2634 default:
2635 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2636 case Mips::BLTImmMacro:
2637 PseudoOpcode = Mips::BLT;
2638 break;
2639 case Mips::BLEImmMacro:
2640 PseudoOpcode = Mips::BLE;
2641 break;
2642 case Mips::BGEImmMacro:
2643 PseudoOpcode = Mips::BGE;
2644 break;
2645 case Mips::BGTImmMacro:
2646 PseudoOpcode = Mips::BGT;
2647 break;
2648 case Mips::BLTUImmMacro:
2649 PseudoOpcode = Mips::BLTU;
2650 break;
2651 case Mips::BLEUImmMacro:
2652 PseudoOpcode = Mips::BLEU;
2653 break;
2654 case Mips::BGEUImmMacro:
2655 PseudoOpcode = Mips::BGEU;
2656 break;
2657 case Mips::BGTUImmMacro:
2658 PseudoOpcode = Mips::BGTU;
2659 break;
2660 case Mips::BLTLImmMacro:
2661 PseudoOpcode = Mips::BLTL;
2662 break;
2663 case Mips::BLELImmMacro:
2664 PseudoOpcode = Mips::BLEL;
2665 break;
2666 case Mips::BGELImmMacro:
2667 PseudoOpcode = Mips::BGEL;
2668 break;
2669 case Mips::BGTLImmMacro:
2670 PseudoOpcode = Mips::BGTL;
2671 break;
2672 case Mips::BLTULImmMacro:
2673 PseudoOpcode = Mips::BLTUL;
2674 break;
2675 case Mips::BLEULImmMacro:
2676 PseudoOpcode = Mips::BLEUL;
2677 break;
2678 case Mips::BGEULImmMacro:
2679 PseudoOpcode = Mips::BGEUL;
2680 break;
2681 case Mips::BGTULImmMacro:
2682 PseudoOpcode = Mips::BGTUL;
2683 break;
2684 }
2685
2686 if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
2687 false, IDLoc, Instructions))
2688 return true;
2689 }
2690
Toma Tabacu1a108322015-06-17 13:20:24 +00002691 switch (PseudoOpcode) {
2692 case Mips::BLT:
2693 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002694 case Mips::BLTL:
2695 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002696 AcceptsEquality = false;
2697 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002698 IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
2699 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002700 ZeroSrcOpcode = Mips::BGTZ;
2701 ZeroTrgOpcode = Mips::BLTZ;
2702 break;
2703 case Mips::BLE:
2704 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002705 case Mips::BLEL:
2706 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002707 AcceptsEquality = true;
2708 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002709 IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
2710 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002711 ZeroSrcOpcode = Mips::BGEZ;
2712 ZeroTrgOpcode = Mips::BLEZ;
2713 break;
2714 case Mips::BGE:
2715 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002716 case Mips::BGEL:
2717 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002718 AcceptsEquality = true;
2719 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002720 IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
2721 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002722 ZeroSrcOpcode = Mips::BLEZ;
2723 ZeroTrgOpcode = Mips::BGEZ;
2724 break;
2725 case Mips::BGT:
2726 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002727 case Mips::BGTL:
2728 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002729 AcceptsEquality = false;
2730 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002731 IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
2732 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002733 ZeroSrcOpcode = Mips::BLTZ;
2734 ZeroTrgOpcode = Mips::BGTZ;
2735 break;
2736 default:
2737 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2738 }
2739
Toma Tabacu1a108322015-06-17 13:20:24 +00002740 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
2741 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
2742 if (IsSrcRegZero && IsTrgRegZero) {
2743 // FIXME: All of these Opcode-specific if's are needed for compatibility
2744 // with GAS' behaviour. However, they may not generate the most efficient
2745 // code in some circumstances.
2746 if (PseudoOpcode == Mips::BLT) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002747 emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2748 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002749 return false;
2750 }
2751 if (PseudoOpcode == Mips::BLE) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002752 emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2753 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002754 Warning(IDLoc, "branch is always taken");
2755 return false;
2756 }
2757 if (PseudoOpcode == Mips::BGE) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002758 emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2759 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002760 Warning(IDLoc, "branch is always taken");
2761 return false;
2762 }
2763 if (PseudoOpcode == Mips::BGT) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002764 emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2765 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002766 return false;
2767 }
2768 if (PseudoOpcode == Mips::BGTU) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002769 emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
2770 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002771 return false;
2772 }
2773 if (AcceptsEquality) {
2774 // If both registers are $0 and the pseudo-branch accepts equality, it
2775 // will always be taken, so we emit an unconditional branch.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002776 emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
2777 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002778 Warning(IDLoc, "branch is always taken");
2779 return false;
2780 }
2781 // If both registers are $0 and the pseudo-branch does not accept
2782 // equality, it will never be taken, so we don't have to emit anything.
2783 return false;
2784 }
2785 if (IsSrcRegZero || IsTrgRegZero) {
2786 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
2787 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
2788 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
2789 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
2790 // the pseudo-branch will never be taken, so we don't emit anything.
2791 // This only applies to unsigned pseudo-branches.
2792 return false;
2793 }
2794 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
2795 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
2796 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
2797 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
2798 // the pseudo-branch will always be taken, so we emit an unconditional
2799 // branch.
2800 // This only applies to unsigned pseudo-branches.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002801 emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
2802 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002803 Warning(IDLoc, "branch is always taken");
2804 return false;
2805 }
2806 if (IsUnsigned) {
2807 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
2808 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
2809 // the pseudo-branch will be taken only when the non-zero register is
2810 // different from 0, so we emit a BNEZ.
2811 //
2812 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
2813 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
2814 // the pseudo-branch will be taken only when the non-zero register is
2815 // equal to 0, so we emit a BEQZ.
2816 //
2817 // Because only BLEU and BGEU branch on equality, we can use the
2818 // AcceptsEquality variable to decide when to emit the BEQZ.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002819 emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
2820 IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
2821 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002822 return false;
2823 }
2824 // If we have a signed pseudo-branch and one of the registers is $0,
2825 // we can use an appropriate compare-to-zero branch. We select which one
2826 // to use in the switch statement above.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002827 emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
2828 IsSrcRegZero ? TrgReg : SrcReg, MCOperand::createExpr(OffsetExpr),
2829 IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002830 return false;
2831 }
2832
2833 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
2834 // expansions. If it is not available, we return.
2835 unsigned ATRegNum = getATReg(IDLoc);
2836 if (!ATRegNum)
2837 return true;
2838
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002839 if (!EmittedNoMacroWarning)
2840 warnIfNoMacro(IDLoc);
Toma Tabacu1a108322015-06-17 13:20:24 +00002841
2842 // SLT fits well with 2 of our 4 pseudo-branches:
2843 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
2844 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
2845 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
2846 // This is accomplished by using a BNEZ with the result of the SLT.
2847 //
2848 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
2849 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
2850 // Because only BGE and BLE branch on equality, we can use the
2851 // AcceptsEquality variable to decide when to emit the BEQZ.
2852 // Note that the order of the SLT arguments doesn't change between
2853 // opposites.
2854 //
2855 // The same applies to the unsigned variants, except that SLTu is used
2856 // instead of SLT.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002857 emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
2858 ReverseOrderSLT ? TrgReg : SrcReg, ReverseOrderSLT ? SrcReg : TrgReg,
2859 IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002860
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002861 emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
2862 : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
2863 ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2864 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002865 return false;
2866}
2867
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002868bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc,
2869 SmallVectorImpl<MCInst> &Instructions,
2870 const bool IsMips64, const bool Signed) {
2871 if (hasMips32r6()) {
2872 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
2873 return false;
2874 }
2875
2876 warnIfNoMacro(IDLoc);
2877
2878 const MCOperand &RsRegOp = Inst.getOperand(0);
2879 assert(RsRegOp.isReg() && "expected register operand kind");
2880 unsigned RsReg = RsRegOp.getReg();
2881
2882 const MCOperand &RtRegOp = Inst.getOperand(1);
2883 assert(RtRegOp.isReg() && "expected register operand kind");
2884 unsigned RtReg = RtRegOp.getReg();
2885 unsigned DivOp;
2886 unsigned ZeroReg;
2887
2888 if (IsMips64) {
2889 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
2890 ZeroReg = Mips::ZERO_64;
2891 } else {
2892 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
2893 ZeroReg = Mips::ZERO;
2894 }
2895
2896 bool UseTraps = useTraps();
2897
2898 if (RsReg == Mips::ZERO || RsReg == Mips::ZERO_64) {
2899 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)
2900 Warning(IDLoc, "dividing zero by zero");
2901 if (IsMips64) {
2902 if (Signed && (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)) {
2903 if (UseTraps) {
2904 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2905 return false;
2906 }
2907
2908 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2909 return false;
2910 }
2911 } else {
2912 emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
2913 return false;
2914 }
2915 }
2916
2917 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
2918 Warning(IDLoc, "division by zero");
2919 if (Signed) {
2920 if (UseTraps) {
2921 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2922 return false;
2923 }
2924
2925 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2926 return false;
2927 }
2928 }
2929
2930 // FIXME: The values for these two BranchTarget variables may be different in
2931 // micromips. These magic numbers need to be removed.
2932 unsigned BranchTargetNoTraps;
2933 unsigned BranchTarget;
2934
2935 if (UseTraps) {
2936 BranchTarget = IsMips64 ? 12 : 8;
2937 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2938 } else {
2939 BranchTarget = IsMips64 ? 20 : 16;
2940 BranchTargetNoTraps = 8;
2941 // Branch to the li instruction.
2942 emitRRI(Mips::BNE, RtReg, ZeroReg, BranchTargetNoTraps, IDLoc,
2943 Instructions);
2944 }
2945
2946 emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
2947
2948 if (!UseTraps)
2949 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2950
2951 if (!Signed) {
2952 emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
2953 return false;
2954 }
2955
2956 unsigned ATReg = getATReg(IDLoc);
2957 if (!ATReg)
2958 return true;
2959
2960 emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, Instructions);
2961 if (IsMips64) {
2962 // Branch to the mflo instruction.
2963 emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
2964 emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, Instructions);
2965 emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, Instructions);
2966 } else {
2967 // Branch to the mflo instruction.
2968 emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
2969 emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, Instructions);
2970 }
2971
2972 if (UseTraps)
2973 emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, Instructions);
2974 else {
2975 // Branch to the mflo instruction.
2976 emitRRI(Mips::BNE, RsReg, ATReg, BranchTargetNoTraps, IDLoc, Instructions);
2977 emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, Instructions);
2978 emitII(Mips::BREAK, 0x6, 0, IDLoc, Instructions);
2979 }
2980 emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
2981 return false;
2982}
2983
Daniel Sanders6394ee52015-10-15 14:52:58 +00002984bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
2985 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacud88d79c2015-06-23 14:39:42 +00002986 if (hasMips32r6() || hasMips64r6()) {
2987 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
2988 return false;
2989 }
2990
2991 warnIfNoMacro(IDLoc);
2992
2993 const MCOperand &DstRegOp = Inst.getOperand(0);
2994 assert(DstRegOp.isReg() && "expected register operand kind");
2995
2996 const MCOperand &SrcRegOp = Inst.getOperand(1);
2997 assert(SrcRegOp.isReg() && "expected register operand kind");
2998
2999 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3000 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3001
3002 unsigned DstReg = DstRegOp.getReg();
3003 unsigned SrcReg = SrcRegOp.getReg();
3004 int64_t OffsetValue = OffsetImmOp.getImm();
3005
3006 // NOTE: We always need AT for ULHU, as it is always used as the source
3007 // register for one of the LBu's.
3008 unsigned ATReg = getATReg(IDLoc);
3009 if (!ATReg)
3010 return true;
3011
3012 // When the value of offset+1 does not fit in 16 bits, we have to load the
3013 // offset in AT, (D)ADDu the original source register (if there was one), and
3014 // then use AT as the source register for the 2 generated LBu's.
3015 bool LoadedOffsetInAT = false;
3016 if (!isInt<16>(OffsetValue + 1) || !isInt<16>(OffsetValue)) {
3017 LoadedOffsetInAT = true;
3018
3019 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003020 true, IDLoc, Instructions))
Toma Tabacud88d79c2015-06-23 14:39:42 +00003021 return true;
3022
3023 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3024 // because it will make our output more similar to GAS'. For example,
3025 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3026 // instead of just an "ori $1, $9, 32768".
3027 // NOTE: If there is no source register specified in the ULHU, the parser
3028 // will interpret it as $0.
3029 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
3030 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
3031 }
3032
3033 unsigned FirstLbuDstReg = LoadedOffsetInAT ? DstReg : ATReg;
3034 unsigned SecondLbuDstReg = LoadedOffsetInAT ? ATReg : DstReg;
3035 unsigned LbuSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3036
3037 int64_t FirstLbuOffset = 0, SecondLbuOffset = 0;
3038 if (isLittle()) {
3039 FirstLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3040 SecondLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3041 } else {
3042 FirstLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3043 SecondLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3044 }
3045
3046 unsigned SllReg = LoadedOffsetInAT ? DstReg : ATReg;
3047
Daniel Sanders6394ee52015-10-15 14:52:58 +00003048 emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
3049 FirstLbuOffset, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003050
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003051 emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondLbuOffset, IDLoc,
3052 Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003053
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003054 emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003055
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003056 emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003057
3058 return false;
3059}
3060
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003061bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc,
3062 SmallVectorImpl<MCInst> &Instructions) {
3063 if (hasMips32r6() || hasMips64r6()) {
3064 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3065 return false;
3066 }
3067
3068 const MCOperand &DstRegOp = Inst.getOperand(0);
3069 assert(DstRegOp.isReg() && "expected register operand kind");
3070
3071 const MCOperand &SrcRegOp = Inst.getOperand(1);
3072 assert(SrcRegOp.isReg() && "expected register operand kind");
3073
3074 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3075 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3076
3077 unsigned SrcReg = SrcRegOp.getReg();
3078 int64_t OffsetValue = OffsetImmOp.getImm();
3079 unsigned ATReg = 0;
3080
3081 // When the value of offset+3 does not fit in 16 bits, we have to load the
3082 // offset in AT, (D)ADDu the original source register (if there was one), and
3083 // then use AT as the source register for the generated LWL and LWR.
3084 bool LoadedOffsetInAT = false;
3085 if (!isInt<16>(OffsetValue + 3) || !isInt<16>(OffsetValue)) {
3086 ATReg = getATReg(IDLoc);
3087 if (!ATReg)
3088 return true;
3089 LoadedOffsetInAT = true;
3090
3091 warnIfNoMacro(IDLoc);
3092
3093 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003094 true, IDLoc, Instructions))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003095 return true;
3096
3097 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3098 // because it will make our output more similar to GAS'. For example,
3099 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3100 // instead of just an "ori $1, $9, 32768".
3101 // NOTE: If there is no source register specified in the ULW, the parser
3102 // will interpret it as $0.
3103 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
3104 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
3105 }
3106
3107 unsigned FinalSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3108 int64_t LeftLoadOffset = 0, RightLoadOffset = 0;
3109 if (isLittle()) {
3110 LeftLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3111 RightLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3112 } else {
3113 LeftLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3114 RightLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3115 }
3116
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003117 emitRRI(Mips::LWL, DstRegOp.getReg(), FinalSrcReg, LeftLoadOffset, IDLoc,
3118 Instructions);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003119
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003120 emitRRI(Mips::LWR, DstRegOp.getReg(), FinalSrcReg, RightLoadOffset, IDLoc,
3121 Instructions);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003122
3123 return false;
3124}
3125
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003126bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
3127 SmallVectorImpl<MCInst> &Instructions) {
3128
3129 assert (Inst.getNumOperands() == 3 && "Invalid operand count");
3130 assert (Inst.getOperand(0).isReg() &&
3131 Inst.getOperand(1).isReg() &&
3132 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
3133
3134 unsigned ATReg = Mips::NoRegister;
3135 unsigned FinalDstReg = Mips::NoRegister;
3136 unsigned DstReg = Inst.getOperand(0).getReg();
3137 unsigned SrcReg = Inst.getOperand(1).getReg();
3138 int64_t ImmValue = Inst.getOperand(2).getImm();
3139
3140 bool Is32Bit = isInt<32>(ImmValue) || isUInt<32>(ImmValue);
3141
3142 unsigned FinalOpcode = Inst.getOpcode();
3143
3144 if (DstReg == SrcReg) {
3145 ATReg = getATReg(Inst.getLoc());
3146 if (!ATReg)
3147 return true;
3148 FinalDstReg = DstReg;
3149 DstReg = ATReg;
3150 }
3151
3152 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Instructions)) {
3153 switch (FinalOpcode) {
3154 default:
3155 llvm_unreachable("unimplemented expansion");
3156 case (Mips::ADDi):
3157 FinalOpcode = Mips::ADD;
3158 break;
3159 case (Mips::ADDiu):
3160 FinalOpcode = Mips::ADDu;
3161 break;
3162 case (Mips::ANDi):
3163 FinalOpcode = Mips::AND;
3164 break;
3165 case (Mips::NORImm):
3166 FinalOpcode = Mips::NOR;
3167 break;
3168 case (Mips::ORi):
3169 FinalOpcode = Mips::OR;
3170 break;
3171 case (Mips::SLTi):
3172 FinalOpcode = Mips::SLT;
3173 break;
3174 case (Mips::SLTiu):
3175 FinalOpcode = Mips::SLTu;
3176 break;
3177 case (Mips::XORi):
3178 FinalOpcode = Mips::XOR;
3179 break;
3180 }
3181
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003182 if (FinalDstReg == Mips::NoRegister)
3183 emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, Instructions);
3184 else
3185 emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc,
3186 Instructions);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003187 return false;
3188 }
3189 return true;
3190}
3191
Toma Tabacu234482a2015-03-16 12:03:39 +00003192void MipsAsmParser::createNop(bool hasShortDelaySlot, SMLoc IDLoc,
3193 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003194 if (hasShortDelaySlot)
3195 emitRR(Mips::MOVE16_MM, Mips::ZERO, Mips::ZERO, IDLoc, Instructions);
3196 else
3197 emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, Instructions);
Toma Tabacu234482a2015-03-16 12:03:39 +00003198}
3199
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003200void MipsAsmParser::createAddu(unsigned DstReg, unsigned SrcReg,
Toma Tabacu0b3e9782015-06-23 14:00:54 +00003201 unsigned TrgReg, bool Is64Bit,
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003202 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanders03f9c012015-07-14 12:24:22 +00003203 emitRRR(Is64Bit ? Mips::DADDu : Mips::ADDu, DstReg, SrcReg, TrgReg, SMLoc(),
3204 Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003205}
3206
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003207void MipsAsmParser::createCpRestoreMemOp(
3208 bool IsLoad, int StackOffset, SMLoc IDLoc,
3209 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003210 // If the offset can not fit into 16 bits, we need to expand.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003211 if (!isInt<16>(StackOffset)) {
3212 MCInst MemInst;
3213 MemInst.setOpcode(IsLoad ? Mips::LW : Mips::SW);
3214 MemInst.addOperand(MCOperand::createReg(Mips::GP));
3215 MemInst.addOperand(MCOperand::createReg(Mips::SP));
3216 MemInst.addOperand(MCOperand::createImm(StackOffset));
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003217 expandMemInst(MemInst, IDLoc, Instructions, IsLoad, true /*HasImmOpnd*/);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003218 return;
3219 }
3220
3221 emitRRI(IsLoad ? Mips::LW : Mips::SW, Mips::GP, Mips::SP, StackOffset, IDLoc,
3222 Instructions);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003223}
3224
Matheus Almeida595fcab2014-06-11 15:05:56 +00003225unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
3226 // As described by the Mips32r2 spec, the registers Rd and Rs for
3227 // jalr.hb must be different.
3228 unsigned Opcode = Inst.getOpcode();
3229
3230 if (Opcode == Mips::JALR_HB &&
3231 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
3232 return Match_RequiresDifferentSrcAndDst;
3233
3234 return Match_Success;
3235}
3236
David Blaikie960ea3f2014-06-08 16:18:35 +00003237bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3238 OperandVector &Operands,
3239 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003240 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00003241 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00003242
Jack Carterb4dbc172012-09-05 23:34:03 +00003243 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00003244 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00003245 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003246 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00003247
3248 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003249 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003250 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00003251 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00003252 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00003253 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00003254 return false;
3255 }
3256 case Match_MissingFeature:
3257 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
3258 return true;
3259 case Match_InvalidOperand: {
3260 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00003261 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003262 if (ErrorInfo >= Operands.size())
3263 return Error(IDLoc, "too few operands for instruction");
3264
David Blaikie960ea3f2014-06-08 16:18:35 +00003265 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00003266 if (ErrorLoc == SMLoc())
3267 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00003268 }
3269
3270 return Error(ErrorLoc, "invalid operand for instruction");
3271 }
3272 case Match_MnemonicFail:
3273 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00003274 case Match_RequiresDifferentSrcAndDst:
3275 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00003276 }
Craig Topper589ceee2015-01-03 08:16:34 +00003277
3278 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00003279}
3280
Toma Tabacud9d344b2015-04-27 14:05:04 +00003281void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
3282 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
3283 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
3284 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003285}
3286
Toma Tabacu81496c12015-05-20 08:54:45 +00003287void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
3288 if (!AssemblerOptions.back()->isMacro())
3289 Warning(Loc, "macro instruction expanded into multiple instructions");
3290}
3291
Daniel Sandersef638fe2014-10-03 15:37:37 +00003292void
3293MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
3294 SMRange Range, bool ShowColors) {
3295 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00003296 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00003297 ShowColors);
3298}
3299
Jack Carter1ac53222013-02-20 23:11:17 +00003300int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003301 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003302
Vladimir Medic4c299852013-11-06 11:27:05 +00003303 CC = StringSwitch<unsigned>(Name)
3304 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003305 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00003306 .Case("a0", 4)
3307 .Case("a1", 5)
3308 .Case("a2", 6)
3309 .Case("a3", 7)
3310 .Case("v0", 2)
3311 .Case("v1", 3)
3312 .Case("s0", 16)
3313 .Case("s1", 17)
3314 .Case("s2", 18)
3315 .Case("s3", 19)
3316 .Case("s4", 20)
3317 .Case("s5", 21)
3318 .Case("s6", 22)
3319 .Case("s7", 23)
3320 .Case("k0", 26)
3321 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003322 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00003323 .Case("sp", 29)
3324 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003325 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00003326 .Case("ra", 31)
3327 .Case("t0", 8)
3328 .Case("t1", 9)
3329 .Case("t2", 10)
3330 .Case("t3", 11)
3331 .Case("t4", 12)
3332 .Case("t5", 13)
3333 .Case("t6", 14)
3334 .Case("t7", 15)
3335 .Case("t8", 24)
3336 .Case("t9", 25)
3337 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003338
Toma Tabacufda445c2014-09-15 15:33:01 +00003339 if (!(isABI_N32() || isABI_N64()))
3340 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003341
Daniel Sandersef638fe2014-10-03 15:37:37 +00003342 if (12 <= CC && CC <= 15) {
3343 // Name is one of t4-t7
3344 AsmToken RegTok = getLexer().peekTok();
3345 SMRange RegRange = RegTok.getLocRange();
3346
3347 StringRef FixedName = StringSwitch<StringRef>(Name)
3348 .Case("t4", "t0")
3349 .Case("t5", "t1")
3350 .Case("t6", "t2")
3351 .Case("t7", "t3")
3352 .Default("");
3353 assert(FixedName != "" && "Register name is not one of t4-t7.");
3354
3355 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
3356 "Did you mean $" + FixedName + "?", RegRange);
3357 }
3358
Toma Tabacufda445c2014-09-15 15:33:01 +00003359 // Although SGI documentation just cuts out t0-t3 for n32/n64,
3360 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
3361 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
3362 if (8 <= CC && CC <= 11)
3363 CC += 4;
3364
3365 if (CC == -1)
3366 CC = StringSwitch<unsigned>(Name)
3367 .Case("a4", 8)
3368 .Case("a5", 9)
3369 .Case("a6", 10)
3370 .Case("a7", 11)
3371 .Case("kt0", 26)
3372 .Case("kt1", 27)
3373 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003374
3375 return CC;
3376}
Jack Carterd0bd6422013-04-18 00:41:53 +00003377
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003378int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
3379 int CC;
3380
3381 CC = StringSwitch<unsigned>(Name)
3382 .Case("hwr_cpunum", 0)
3383 .Case("hwr_synci_step", 1)
3384 .Case("hwr_cc", 2)
3385 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00003386 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003387 .Default(-1);
3388
3389 return CC;
3390}
3391
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003392int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003393
Jack Cartera63b16a2012-09-07 00:23:42 +00003394 if (Name[0] == 'f') {
3395 StringRef NumString = Name.substr(1);
3396 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003397 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003398 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003399 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00003400 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003401 return IntVal;
3402 }
3403 return -1;
3404}
Jack Cartera63b16a2012-09-07 00:23:42 +00003405
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003406int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
3407
3408 if (Name.startswith("fcc")) {
3409 StringRef NumString = Name.substr(3);
3410 unsigned IntVal;
3411 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003412 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003413 if (IntVal > 7) // There are only 8 fcc registers.
3414 return -1;
3415 return IntVal;
3416 }
3417 return -1;
3418}
3419
3420int MipsAsmParser::matchACRegisterName(StringRef Name) {
3421
Akira Hatanaka274d24c2013-08-14 01:15:52 +00003422 if (Name.startswith("ac")) {
3423 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003424 unsigned IntVal;
3425 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003426 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003427 if (IntVal > 3) // There are only 3 acc registers.
3428 return -1;
3429 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00003430 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003431 return -1;
3432}
Jack Carterd0bd6422013-04-18 00:41:53 +00003433
Jack Carter5dc8ac92013-09-25 23:50:44 +00003434int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
3435 unsigned IntVal;
3436
3437 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
3438 return -1;
3439
3440 if (IntVal > 31)
3441 return -1;
3442
3443 return IntVal;
3444}
3445
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003446int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
3447 int CC;
3448
3449 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00003450 .Case("msair", 0)
3451 .Case("msacsr", 1)
3452 .Case("msaaccess", 2)
3453 .Case("msasave", 3)
3454 .Case("msamodify", 4)
3455 .Case("msarequest", 5)
3456 .Case("msamap", 6)
3457 .Case("msaunmap", 7)
3458 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003459
3460 return CC;
3461}
3462
Toma Tabacu89a712b2015-04-15 10:48:56 +00003463unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00003464 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00003465 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00003466 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00003467 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00003468 return 0;
3469 }
3470 unsigned AT = getReg(
3471 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00003472 return AT;
3473}
Jack Carter0b744b32012-10-04 02:29:46 +00003474
Jack Carterd0bd6422013-04-18 00:41:53 +00003475unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00003476 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00003477}
3478
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003479unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003480 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00003481 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003482}
3483
Jack Carter873c7242013-01-12 01:03:14 +00003484int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003485 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00003486 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00003487 return -1;
3488
Jack Carter873c7242013-01-12 01:03:14 +00003489 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00003490}
3491
Toma Tabacu13964452014-09-04 13:23:44 +00003492bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003493 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00003494 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003495
Jack Carter30a59822012-10-04 04:03:53 +00003496 // Check if the current operand has a custom associated parser, if so, try to
3497 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00003498 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3499 if (ResTy == MatchOperand_Success)
3500 return false;
3501 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3502 // there was a match, but an error occurred, in which case, just return that
3503 // the operand parsing failed.
3504 if (ResTy == MatchOperand_ParseFail)
3505 return true;
3506
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003507 DEBUG(dbgs() << ".. Generic Parser\n");
3508
Jack Carterb4dbc172012-09-05 23:34:03 +00003509 switch (getLexer().getKind()) {
3510 default:
3511 Error(Parser.getTok().getLoc(), "unexpected token in operand");
3512 return true;
3513 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003514 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00003515 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00003516
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003517 // Almost all registers have been parsed by custom parsers. There is only
3518 // one exception to this. $zero (and it's alias $0) will reach this point
3519 // for div, divu, and similar instructions because it is not an operand
3520 // to the instruction definition but an explicit register. Special case
3521 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00003522 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00003523 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003524
Jack Carterd0bd6422013-04-18 00:41:53 +00003525 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00003526 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003527 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00003528 return true;
3529
Jack Carter873c7242013-01-12 01:03:14 +00003530 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00003531 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00003532 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00003533 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003534 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00003535
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003536 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003537 return false;
3538 }
Vladimir Medic4c299852013-11-06 11:27:05 +00003539 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00003540 case AsmToken::LParen:
3541 case AsmToken::Minus:
3542 case AsmToken::Plus:
3543 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00003544 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00003545 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003546 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00003547 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003548 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00003549 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00003550 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003551 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003552 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003553 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00003554 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00003555 return true;
3556
Jack Carter873c7242013-01-12 01:03:14 +00003557 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3558
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003559 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00003560 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003561 } // case AsmToken::Percent
3562 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00003563 return true;
3564}
3565
Vladimir Medic4c299852013-11-06 11:27:05 +00003566const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00003567 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00003568 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00003569 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00003570 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00003571 // It's a constant, evaluate reloc value.
3572 int16_t Val;
3573 switch (getVariantKind(RelocStr)) {
3574 case MCSymbolRefExpr::VK_Mips_ABS_LO:
3575 // Get the 1st 16-bits.
3576 Val = MCE->getValue() & 0xffff;
3577 break;
3578 case MCSymbolRefExpr::VK_Mips_ABS_HI:
3579 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
3580 // 16 bits being negative.
3581 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
3582 break;
3583 case MCSymbolRefExpr::VK_Mips_HIGHER:
3584 // Get the 3rd 16-bits.
3585 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
3586 break;
3587 case MCSymbolRefExpr::VK_Mips_HIGHEST:
3588 // Get the 4th 16-bits.
3589 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
3590 break;
3591 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00003592 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00003593 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00003594 return MCConstantExpr::create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00003595 }
3596
Jack Carterb5cf5902013-04-17 00:18:04 +00003597 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003598 // It's a symbol, create a symbolic expression from the symbol.
Toma Tabacu07c97b32015-06-17 10:43:45 +00003599 const MCSymbol *Symbol = &MSRE->getSymbol();
Jack Carterb5cf5902013-04-17 00:18:04 +00003600 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003601 Res = MCSymbolRefExpr::create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003602 return Res;
3603 }
3604
3605 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00003606 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
3607
Sasa Stankovic06c47802014-04-03 10:37:45 +00003608 // Try to create target expression.
3609 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
Jim Grosbach13760bd2015-05-30 01:25:56 +00003610 return MipsMCExpr::create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00003611
Jack Carterd0bd6422013-04-18 00:41:53 +00003612 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
3613 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003614 Res = MCBinaryExpr::create(BE->getOpcode(), LExp, RExp, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003615 return Res;
3616 }
3617
3618 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003619 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003620 Res = MCUnaryExpr::create(UN->getOpcode(), UnExp, getContext());
Jack Carterd0bd6422013-04-18 00:41:53 +00003621 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00003622 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003623 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00003624 return Expr;
3625}
3626
3627bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
3628
3629 switch (Expr->getKind()) {
3630 case MCExpr::Constant:
3631 return true;
3632 case MCExpr::SymbolRef:
3633 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
3634 case MCExpr::Binary:
3635 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
3636 if (!isEvaluated(BE->getLHS()))
3637 return false;
3638 return isEvaluated(BE->getRHS());
3639 }
3640 case MCExpr::Unary:
3641 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00003642 case MCExpr::Target:
3643 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003644 }
Jack Carterb5cf5902013-04-17 00:18:04 +00003645 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00003646}
Jack Carterd0bd6422013-04-18 00:41:53 +00003647
Jack Carterb5cf5902013-04-17 00:18:04 +00003648bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003649 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00003650 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00003651 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00003652 if (Tok.isNot(AsmToken::Identifier))
3653 return true;
3654
Yaron Keren075759a2015-03-30 15:42:36 +00003655 std::string Str = Tok.getIdentifier();
Jack Carterb5cf5902013-04-17 00:18:04 +00003656
Jack Carterd0bd6422013-04-18 00:41:53 +00003657 Parser.Lex(); // Eat the identifier.
3658 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003659 const MCExpr *IdVal;
3660 SMLoc EndLoc;
3661
3662 if (getLexer().getKind() == AsmToken::LParen) {
3663 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003664 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003665 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003666 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003667 const AsmToken &nextTok = Parser.getTok();
3668 if (nextTok.isNot(AsmToken::Identifier))
3669 return true;
3670 Str += "(%";
3671 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00003672 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00003673 if (getLexer().getKind() != AsmToken::LParen)
3674 return true;
3675 } else
3676 break;
3677 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003678 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00003679 return true;
3680
3681 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00003682 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003683
3684 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00003685 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003686
Jack Carterd0bd6422013-04-18 00:41:53 +00003687 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00003688 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003689}
3690
Jack Carterb4dbc172012-09-05 23:34:03 +00003691bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
3692 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003693 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00003694 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003695 if (ResTy == MatchOperand_Success) {
3696 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00003697 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003698 StartLoc = Operand.getStartLoc();
3699 EndLoc = Operand.getEndLoc();
3700
3701 // AFAIK, we only support numeric registers and named GPR's in CFI
3702 // directives.
3703 // Don't worry about eating tokens before failing. Using an unrecognised
3704 // register is a parse error.
3705 if (Operand.isGPRAsmReg()) {
3706 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003707 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003708 }
3709
3710 return (RegNo == (unsigned)-1);
3711 }
3712
3713 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00003714 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00003715}
3716
Jack Carterb5cf5902013-04-17 00:18:04 +00003717bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003718 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00003719 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00003720 bool Result = true;
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003721 unsigned NumOfLParen = 0;
Jack Carterb5cf5902013-04-17 00:18:04 +00003722
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003723 while (getLexer().getKind() == AsmToken::LParen) {
Jack Carterb5cf5902013-04-17 00:18:04 +00003724 Parser.Lex();
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003725 ++NumOfLParen;
3726 }
Jack Carter873c7242013-01-12 01:03:14 +00003727
Jack Carterd0bd6422013-04-18 00:41:53 +00003728 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00003729 default:
3730 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00003731 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00003732 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00003733 case AsmToken::Integer:
3734 case AsmToken::Minus:
3735 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00003736 if (isParenExpr)
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003737 Result = getParser().parseParenExprOfDepth(NumOfLParen, Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00003738 else
3739 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00003740 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00003741 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003742 break;
Jack Carter873c7242013-01-12 01:03:14 +00003743 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00003744 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00003745 }
Jack Carterb5cf5902013-04-17 00:18:04 +00003746 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003747}
3748
David Blaikie960ea3f2014-06-08 16:18:35 +00003749MipsAsmParser::OperandMatchResultTy
3750MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003751 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003752 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00003753 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00003754 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00003755 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003756 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00003757 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00003758 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00003759
Jack Carterb5cf5902013-04-17 00:18:04 +00003760 if (getLexer().getKind() == AsmToken::LParen) {
3761 Parser.Lex();
3762 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003763 }
3764
Jack Carterb5cf5902013-04-17 00:18:04 +00003765 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003766 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00003767 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003768
Jack Carterd0bd6422013-04-18 00:41:53 +00003769 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003770 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003771 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003772 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00003773 SMLoc E =
3774 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003775 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00003776 return MatchOperand_Success;
3777 }
3778 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003779 SMLoc E =
3780 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00003781
Jack Carterd0bd6422013-04-18 00:41:53 +00003782 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00003783 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00003784 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00003785 S, E, *this);
3786 Operands.push_back(
3787 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00003788 return MatchOperand_Success;
3789 }
3790 Error(Parser.getTok().getLoc(), "'(' expected");
3791 return MatchOperand_ParseFail;
3792 }
3793
Jack Carterd0bd6422013-04-18 00:41:53 +00003794 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003795 }
3796
Toma Tabacu13964452014-09-04 13:23:44 +00003797 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003798 if (Res != MatchOperand_Success)
3799 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003800
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003801 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00003802 Error(Parser.getTok().getLoc(), "')' expected");
3803 return MatchOperand_ParseFail;
3804 }
3805
Jack Carter873c7242013-01-12 01:03:14 +00003806 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3807
Jack Carterd0bd6422013-04-18 00:41:53 +00003808 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003809
Craig Topper062a2ba2014-04-25 05:30:21 +00003810 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003811 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00003812
Jack Carterd0bd6422013-04-18 00:41:53 +00003813 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00003814 std::unique_ptr<MipsOperand> op(
3815 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00003816 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00003817 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003818 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00003819 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003820 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
3821 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00003822 if (IdVal->evaluateAsAbsolute(Imm))
3823 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003824 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003825 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00003826 getContext());
3827 }
3828
David Blaikie960ea3f2014-06-08 16:18:35 +00003829 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003830 return MatchOperand_Success;
3831}
3832
David Blaikie960ea3f2014-06-08 16:18:35 +00003833bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003834 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00003835 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00003836 if (Sym) {
3837 SMLoc S = Parser.getTok().getLoc();
3838 const MCExpr *Expr;
3839 if (Sym->isVariable())
3840 Expr = Sym->getVariableValue();
3841 else
3842 return false;
3843 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003844 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00003845 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00003846 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003847 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00003848 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00003849 if (ResTy == MatchOperand_Success) {
3850 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00003851 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00003852 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003853 llvm_unreachable("Should never ParseFail");
3854 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00003855 }
3856 } else if (Expr->getKind() == MCExpr::Constant) {
3857 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00003858 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00003859 Operands.push_back(
3860 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00003861 return true;
3862 }
3863 }
3864 return false;
3865}
Jack Carterd0bd6422013-04-18 00:41:53 +00003866
Jack Carter873c7242013-01-12 01:03:14 +00003867MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003868MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00003869 StringRef Identifier,
3870 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003871 int Index = matchCPURegisterName(Identifier);
3872 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003873 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003874 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3875 return MatchOperand_Success;
3876 }
3877
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003878 Index = matchHWRegsRegisterName(Identifier);
3879 if (Index != -1) {
3880 Operands.push_back(MipsOperand::createHWRegsReg(
3881 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3882 return MatchOperand_Success;
3883 }
3884
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003885 Index = matchFPURegisterName(Identifier);
3886 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003887 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003888 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3889 return MatchOperand_Success;
3890 }
3891
3892 Index = matchFCCRegisterName(Identifier);
3893 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003894 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003895 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3896 return MatchOperand_Success;
3897 }
3898
3899 Index = matchACRegisterName(Identifier);
3900 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003901 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003902 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3903 return MatchOperand_Success;
3904 }
3905
3906 Index = matchMSA128RegisterName(Identifier);
3907 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003908 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003909 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3910 return MatchOperand_Success;
3911 }
3912
3913 Index = matchMSA128CtrlRegisterName(Identifier);
3914 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003915 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003916 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3917 return MatchOperand_Success;
3918 }
3919
3920 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00003921}
3922
3923MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003924MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003925 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00003926 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003927
3928 if (Token.is(AsmToken::Identifier)) {
3929 DEBUG(dbgs() << ".. identifier\n");
3930 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00003931 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00003932 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00003933 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003934 } else if (Token.is(AsmToken::Integer)) {
3935 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00003936 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003937 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
3938 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003939 return MatchOperand_Success;
3940 }
3941
3942 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
3943
3944 return MatchOperand_NoMatch;
3945}
3946
David Blaikie960ea3f2014-06-08 16:18:35 +00003947MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003948MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003949 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00003950 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003951
3952 auto Token = Parser.getTok();
3953
3954 SMLoc S = Token.getLoc();
3955
3956 if (Token.isNot(AsmToken::Dollar)) {
3957 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
3958 if (Token.is(AsmToken::Identifier)) {
3959 if (searchSymbolAlias(Operands))
3960 return MatchOperand_Success;
3961 }
3962 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
3963 return MatchOperand_NoMatch;
3964 }
3965 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003966
Toma Tabacu13964452014-09-04 13:23:44 +00003967 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00003968 if (ResTy == MatchOperand_Success) {
3969 Parser.Lex(); // $
3970 Parser.Lex(); // identifier
3971 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003972 return ResTy;
3973}
3974
3975MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003976MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003977 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003978 switch (getLexer().getKind()) {
3979 default:
3980 return MatchOperand_NoMatch;
3981 case AsmToken::LParen:
3982 case AsmToken::Minus:
3983 case AsmToken::Plus:
3984 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00003985 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003986 case AsmToken::String:
3987 break;
3988 }
3989
3990 const MCExpr *IdVal;
3991 SMLoc S = Parser.getTok().getLoc();
3992 if (getParser().parseExpression(IdVal))
3993 return MatchOperand_ParseFail;
3994
3995 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3996 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
3997 return MatchOperand_Success;
3998}
3999
David Blaikie960ea3f2014-06-08 16:18:35 +00004000MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004001MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004002 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004003 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004004
4005 SMLoc S = getLexer().getLoc();
4006
4007 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00004008 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004009 if (ResTy != MatchOperand_NoMatch)
4010 return ResTy;
4011
Daniel Sanders315386c2014-04-01 10:40:14 +00004012 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00004013 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00004014 if (ResTy != MatchOperand_NoMatch)
4015 return ResTy;
4016
Daniel Sandersffd84362014-04-01 10:41:48 +00004017 const MCExpr *Expr = nullptr;
4018 if (Parser.parseExpression(Expr)) {
4019 // We have no way of knowing if a symbol was consumed so we must ParseFail
4020 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004021 }
Daniel Sandersffd84362014-04-01 10:41:48 +00004022 Operands.push_back(
4023 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004024 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00004025}
4026
Vladimir Medic2b953d02013-10-01 09:48:56 +00004027MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00004028MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004029 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00004030 const MCExpr *IdVal;
4031 // If the first token is '$' we may have register operand.
4032 if (Parser.getTok().is(AsmToken::Dollar))
4033 return MatchOperand_NoMatch;
4034 SMLoc S = Parser.getTok().getLoc();
4035 if (getParser().parseExpression(IdVal))
4036 return MatchOperand_ParseFail;
4037 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00004038 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00004039 int64_t Val = MCE->getValue();
4040 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4041 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00004042 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00004043 return MatchOperand_Success;
4044}
4045
Matheus Almeida779c5932013-11-18 12:32:49 +00004046MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004047MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004048 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00004049 switch (getLexer().getKind()) {
4050 default:
4051 return MatchOperand_NoMatch;
4052 case AsmToken::LParen:
4053 case AsmToken::Plus:
4054 case AsmToken::Minus:
4055 case AsmToken::Integer:
4056 break;
4057 }
4058
4059 const MCExpr *Expr;
4060 SMLoc S = Parser.getTok().getLoc();
4061
4062 if (getParser().parseExpression(Expr))
4063 return MatchOperand_ParseFail;
4064
4065 int64_t Val;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004066 if (!Expr->evaluateAsAbsolute(Val)) {
Matheus Almeida779c5932013-11-18 12:32:49 +00004067 Error(S, "expected immediate value");
4068 return MatchOperand_ParseFail;
4069 }
4070
4071 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
4072 // and because the CPU always adds one to the immediate field, the allowed
4073 // range becomes 1..4. We'll only check the range here and will deal
4074 // with the addition/subtraction when actually decoding/encoding
4075 // the instruction.
4076 if (Val < 1 || Val > 4) {
4077 Error(S, "immediate not in range (1..4)");
4078 return MatchOperand_ParseFail;
4079 }
4080
Jack Carter3b2c96e2014-01-22 23:31:38 +00004081 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004082 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00004083 return MatchOperand_Success;
4084}
4085
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004086MipsAsmParser::OperandMatchResultTy
4087MipsAsmParser::parseRegisterList(OperandVector &Operands) {
4088 MCAsmParser &Parser = getParser();
4089 SmallVector<unsigned, 10> Regs;
4090 unsigned RegNo;
4091 unsigned PrevReg = Mips::NoRegister;
4092 bool RegRange = false;
4093 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4094
4095 if (Parser.getTok().isNot(AsmToken::Dollar))
4096 return MatchOperand_ParseFail;
4097
4098 SMLoc S = Parser.getTok().getLoc();
4099 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
4100 SMLoc E = getLexer().getLoc();
4101 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
4102 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
4103 if (RegRange) {
4104 // Remove last register operand because registers from register range
4105 // should be inserted first.
4106 if (RegNo == Mips::RA) {
4107 Regs.push_back(RegNo);
4108 } else {
4109 unsigned TmpReg = PrevReg + 1;
4110 while (TmpReg <= RegNo) {
4111 if ((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) {
4112 Error(E, "invalid register operand");
4113 return MatchOperand_ParseFail;
4114 }
4115
4116 PrevReg = TmpReg;
4117 Regs.push_back(TmpReg++);
4118 }
4119 }
4120
4121 RegRange = false;
4122 } else {
4123 if ((PrevReg == Mips::NoRegister) && (RegNo != Mips::S0) &&
4124 (RegNo != Mips::RA)) {
4125 Error(E, "$16 or $31 expected");
4126 return MatchOperand_ParseFail;
4127 } else if (((RegNo < Mips::S0) || (RegNo > Mips::S7)) &&
4128 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
4129 Error(E, "invalid register operand");
4130 return MatchOperand_ParseFail;
4131 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
4132 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
4133 Error(E, "consecutive register numbers expected");
4134 return MatchOperand_ParseFail;
4135 }
4136
4137 Regs.push_back(RegNo);
4138 }
4139
4140 if (Parser.getTok().is(AsmToken::Minus))
4141 RegRange = true;
4142
4143 if (!Parser.getTok().isNot(AsmToken::Minus) &&
4144 !Parser.getTok().isNot(AsmToken::Comma)) {
4145 Error(E, "',' or '-' expected");
4146 return MatchOperand_ParseFail;
4147 }
4148
4149 Lex(); // Consume comma or minus
4150 if (Parser.getTok().isNot(AsmToken::Dollar))
4151 break;
4152
4153 PrevReg = RegNo;
4154 }
4155
4156 SMLoc E = Parser.getTok().getLoc();
4157 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4158 parseMemOperand(Operands);
4159 return MatchOperand_Success;
4160}
4161
Zoran Jovanovic2deca342014-12-16 14:59:10 +00004162MipsAsmParser::OperandMatchResultTy
4163MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
4164 MCAsmParser &Parser = getParser();
4165
4166 SMLoc S = Parser.getTok().getLoc();
4167 if (parseAnyRegister(Operands) != MatchOperand_Success)
4168 return MatchOperand_ParseFail;
4169
4170 SMLoc E = Parser.getTok().getLoc();
4171 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
4172 unsigned Reg = Op.getGPR32Reg();
4173 Operands.pop_back();
4174 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
4175 return MatchOperand_Success;
4176}
4177
Zoran Jovanovic41688672015-02-10 16:36:20 +00004178MipsAsmParser::OperandMatchResultTy
4179MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
4180 MCAsmParser &Parser = getParser();
4181 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4182 SmallVector<unsigned, 10> Regs;
4183
4184 if (Parser.getTok().isNot(AsmToken::Dollar))
4185 return MatchOperand_ParseFail;
4186
4187 SMLoc S = Parser.getTok().getLoc();
4188
4189 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4190 return MatchOperand_ParseFail;
4191
4192 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4193 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4194 Regs.push_back(RegNo);
4195
4196 SMLoc E = Parser.getTok().getLoc();
4197 if (Parser.getTok().isNot(AsmToken::Comma)) {
4198 Error(E, "',' expected");
4199 return MatchOperand_ParseFail;
4200 }
4201
4202 // Remove comma.
4203 Parser.Lex();
4204
4205 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4206 return MatchOperand_ParseFail;
4207
4208 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4209 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4210 Regs.push_back(RegNo);
4211
4212 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4213
4214 return MatchOperand_Success;
4215}
4216
Jack Carterdc1e35d2012-09-06 20:00:02 +00004217MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
4218
Vladimir Medic4c299852013-11-06 11:27:05 +00004219 MCSymbolRefExpr::VariantKind VK =
4220 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
4221 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
4222 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
4223 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
4224 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
4225 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
4226 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
4227 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
4228 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
4229 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
4230 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
4231 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
4232 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
4233 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
4234 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
4235 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
4236 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
4237 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00004238 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
4239 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
4240 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
4241 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
4242 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
4243 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00004244 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
4245 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00004246 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00004247
Matheus Almeida2852af82014-04-22 10:15:54 +00004248 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00004249
Jack Carterdc1e35d2012-09-06 20:00:02 +00004250 return VK;
4251}
Jack Cartera63b16a2012-09-07 00:23:42 +00004252
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004253/// Sometimes (i.e. load/stores) the operand may be followed immediately by
4254/// either this.
4255/// ::= '(', register, ')'
4256/// handle it before we iterate so we don't get tripped up by the lack of
4257/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004258bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004259 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004260 if (getLexer().is(AsmToken::LParen)) {
4261 Operands.push_back(
4262 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
4263 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004264 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004265 SMLoc Loc = getLexer().getLoc();
4266 Parser.eatToEndOfStatement();
4267 return Error(Loc, "unexpected token in argument list");
4268 }
4269 if (Parser.getTok().isNot(AsmToken::RParen)) {
4270 SMLoc Loc = getLexer().getLoc();
4271 Parser.eatToEndOfStatement();
4272 return Error(Loc, "unexpected token, expected ')'");
4273 }
4274 Operands.push_back(
4275 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
4276 Parser.Lex();
4277 }
4278 return false;
4279}
4280
4281/// Sometimes (i.e. in MSA) the operand may be followed immediately by
4282/// either one of these.
4283/// ::= '[', register, ']'
4284/// ::= '[', integer, ']'
4285/// handle it before we iterate so we don't get tripped up by the lack of
4286/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004287bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00004288 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004289 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004290 if (getLexer().is(AsmToken::LBrac)) {
4291 Operands.push_back(
4292 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
4293 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004294 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004295 SMLoc Loc = getLexer().getLoc();
4296 Parser.eatToEndOfStatement();
4297 return Error(Loc, "unexpected token in argument list");
4298 }
4299 if (Parser.getTok().isNot(AsmToken::RBrac)) {
4300 SMLoc Loc = getLexer().getLoc();
4301 Parser.eatToEndOfStatement();
4302 return Error(Loc, "unexpected token, expected ']'");
4303 }
4304 Operands.push_back(
4305 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
4306 Parser.Lex();
4307 }
4308 return false;
4309}
4310
David Blaikie960ea3f2014-06-08 16:18:35 +00004311bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
4312 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004313 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004314 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004315
4316 // We have reached first instruction, module directive are now forbidden.
4317 getTargetStreamer().forbidModuleDirective();
4318
Vladimir Medic74593e62013-07-17 15:00:42 +00004319 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00004320 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00004321 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00004322 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00004323 }
Vladimir Medic64828a12013-07-16 10:07:14 +00004324 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004325 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004326
4327 // Read the remaining operands.
4328 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4329 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004330 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004331 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004332 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004333 return Error(Loc, "unexpected token in argument list");
4334 }
Toma Tabacu13964452014-09-04 13:23:44 +00004335 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004336 return true;
4337 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00004338
Jack Carterd0bd6422013-04-18 00:41:53 +00004339 while (getLexer().is(AsmToken::Comma)) {
4340 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00004341 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004342 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004343 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004344 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004345 return Error(Loc, "unexpected token in argument list");
4346 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004347 // Parse bracket and parenthesis suffixes before we iterate
4348 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00004349 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004350 return true;
4351 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00004352 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004353 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00004354 }
4355 }
Jack Carterb4dbc172012-09-05 23:34:03 +00004356 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4357 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004358 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004359 return Error(Loc, "unexpected token in argument list");
4360 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004361 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00004362 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00004363}
4364
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004365bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004366 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004367 SMLoc Loc = getLexer().getLoc();
4368 Parser.eatToEndOfStatement();
4369 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00004370}
4371
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004372bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004373 return Error(Loc, ErrorMsg);
4374}
4375
Jack Carter0b744b32012-10-04 02:29:46 +00004376bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004377 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004378 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00004379
4380 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00004381 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00004382
4383 Parser.Lex(); // Eat "noat".
4384
Jack Carterd0bd6422013-04-18 00:41:53 +00004385 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004386 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004387 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004388 return false;
4389 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004390
4391 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004392 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004393 return false;
4394}
Jack Carterd0bd6422013-04-18 00:41:53 +00004395
Jack Carter0b744b32012-10-04 02:29:46 +00004396bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00004397 // Line can be: ".set at", which sets $at to $1
4398 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00004399 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00004400 Parser.Lex(); // Eat "at".
4401
Jack Carter0b744b32012-10-04 02:29:46 +00004402 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004403 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00004404 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00004405
4406 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004407 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004408 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00004409 }
4410
4411 if (getLexer().isNot(AsmToken::Equal)) {
4412 reportParseError("unexpected token, expected equals sign");
4413 return false;
4414 }
4415 Parser.Lex(); // Eat "=".
4416
4417 if (getLexer().isNot(AsmToken::Dollar)) {
4418 if (getLexer().is(AsmToken::EndOfStatement)) {
4419 reportParseError("no register specified");
4420 return false;
4421 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00004422 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00004423 return false;
4424 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004425 }
4426 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00004427
Toma Tabacu16a74492015-02-13 10:30:57 +00004428 // Find out what "reg" is.
4429 unsigned AtRegNo;
4430 const AsmToken &Reg = Parser.getTok();
4431 if (Reg.is(AsmToken::Identifier)) {
4432 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
4433 } else if (Reg.is(AsmToken::Integer)) {
4434 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00004435 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00004436 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00004437 return false;
4438 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004439
4440 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00004441 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004442 reportParseError("invalid register");
4443 return false;
4444 }
4445 Parser.Lex(); // Eat "reg".
4446
4447 // If this is not the end of the statement, report an error.
4448 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4449 reportParseError("unexpected token, expected end of statement");
4450 return false;
4451 }
4452
4453 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
4454
4455 Parser.Lex(); // Consume the EndOfStatement.
4456 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004457}
4458
4459bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004460 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004461 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004462 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004463 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004464 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004465 return false;
4466 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004467 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00004468 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004469 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004470 return false;
4471}
4472
4473bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004474 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004475 Parser.Lex();
4476 // If this is not the end of the statement, report an error.
4477 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004478 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004479 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00004480 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004481 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00004482 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004483 Parser.Lex(); // Consume the EndOfStatement.
4484 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004485}
4486
4487bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004488 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004489 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004490 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004491 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004492 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004493 return false;
4494 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004495 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00004496 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00004497 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004498 return false;
4499}
4500
4501bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004502 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004503 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004504 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004505 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004506 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004507 return false;
4508 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004509 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00004510 reportParseError("`noreorder' must be set before `nomacro'");
4511 return false;
4512 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004513 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00004514 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00004515 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004516 return false;
4517}
Jack Carterd76b2372013-03-21 21:44:16 +00004518
Daniel Sanders44934432014-08-07 12:03:36 +00004519bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004520 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00004521 Parser.Lex();
4522
4523 // If this is not the end of the statement, report an error.
4524 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004525 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00004526
4527 setFeatureBits(Mips::FeatureMSA, "msa");
4528 getTargetStreamer().emitDirectiveSetMsa();
4529 return false;
4530}
4531
4532bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004533 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00004534 Parser.Lex();
4535
4536 // If this is not the end of the statement, report an error.
4537 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004538 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00004539
4540 clearFeatureBits(Mips::FeatureMSA, "msa");
4541 getTargetStreamer().emitDirectiveSetNoMsa();
4542 return false;
4543}
4544
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004545bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004546 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004547 Parser.Lex(); // Eat "nodsp".
4548
4549 // If this is not the end of the statement, report an error.
4550 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4551 reportParseError("unexpected token, expected end of statement");
4552 return false;
4553 }
4554
4555 clearFeatureBits(Mips::FeatureDSP, "dsp");
4556 getTargetStreamer().emitDirectiveSetNoDsp();
4557 return false;
4558}
4559
Toma Tabacucc2502d2014-11-04 17:18:07 +00004560bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004561 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00004562 Parser.Lex(); // Eat "mips16".
4563
Jack Carter39536722014-01-22 23:08:42 +00004564 // If this is not the end of the statement, report an error.
4565 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004566 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00004567 return false;
4568 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00004569
4570 setFeatureBits(Mips::FeatureMips16, "mips16");
4571 getTargetStreamer().emitDirectiveSetMips16();
4572 Parser.Lex(); // Consume the EndOfStatement.
4573 return false;
4574}
4575
4576bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004577 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00004578 Parser.Lex(); // Eat "nomips16".
4579
4580 // If this is not the end of the statement, report an error.
4581 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4582 reportParseError("unexpected token, expected end of statement");
4583 return false;
4584 }
4585
4586 clearFeatureBits(Mips::FeatureMips16, "mips16");
4587 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00004588 Parser.Lex(); // Consume the EndOfStatement.
4589 return false;
4590}
4591
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004592bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004593 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004594 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004595 // Line can be: .set fp=32
4596 // .set fp=xx
4597 // .set fp=64
4598 Parser.Lex(); // Eat fp token
4599 AsmToken Tok = Parser.getTok();
4600 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004601 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004602 return false;
4603 }
4604 Parser.Lex(); // Eat '=' token.
4605 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004606
4607 if (!parseFpABIValue(FpAbiVal, ".set"))
4608 return false;
4609
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004610 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004611 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004612 return false;
4613 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004614 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004615 Parser.Lex(); // Consume the EndOfStatement.
4616 return false;
4617}
4618
Toma Tabacu32c72aa2015-06-30 09:36:50 +00004619bool MipsAsmParser::parseSetOddSPRegDirective() {
4620 MCAsmParser &Parser = getParser();
4621
4622 Parser.Lex(); // Eat "oddspreg".
4623 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4624 reportParseError("unexpected token, expected end of statement");
4625 return false;
4626 }
4627
4628 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4629 getTargetStreamer().emitDirectiveSetOddSPReg();
4630 return false;
4631}
4632
4633bool MipsAsmParser::parseSetNoOddSPRegDirective() {
4634 MCAsmParser &Parser = getParser();
4635
4636 Parser.Lex(); // Eat "nooddspreg".
4637 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4638 reportParseError("unexpected token, expected end of statement");
4639 return false;
4640 }
4641
4642 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4643 getTargetStreamer().emitDirectiveSetNoOddSPReg();
4644 return false;
4645}
4646
Toma Tabacu9db22db2014-09-09 10:15:38 +00004647bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004648 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00004649 SMLoc Loc = getLexer().getLoc();
4650
4651 Parser.Lex();
4652 if (getLexer().isNot(AsmToken::EndOfStatement))
4653 return reportParseError("unexpected token, expected end of statement");
4654
4655 // Always keep an element on the options "stack" to prevent the user
4656 // from changing the initial options. This is how we remember them.
4657 if (AssemblerOptions.size() == 2)
4658 return reportParseError(Loc, ".set pop with no .set push");
4659
4660 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00004661 setAvailableFeatures(
4662 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
4663 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00004664
4665 getTargetStreamer().emitDirectiveSetPop();
4666 return false;
4667}
4668
4669bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004670 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00004671 Parser.Lex();
4672 if (getLexer().isNot(AsmToken::EndOfStatement))
4673 return reportParseError("unexpected token, expected end of statement");
4674
4675 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00004676 AssemblerOptions.push_back(
4677 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00004678
4679 getTargetStreamer().emitDirectiveSetPush();
4680 return false;
4681}
4682
Toma Tabacu29696502015-06-02 09:48:04 +00004683bool MipsAsmParser::parseSetSoftFloatDirective() {
4684 MCAsmParser &Parser = getParser();
4685 Parser.Lex();
4686 if (getLexer().isNot(AsmToken::EndOfStatement))
4687 return reportParseError("unexpected token, expected end of statement");
4688
4689 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
4690 getTargetStreamer().emitDirectiveSetSoftFloat();
4691 return false;
4692}
4693
4694bool MipsAsmParser::parseSetHardFloatDirective() {
4695 MCAsmParser &Parser = getParser();
4696 Parser.Lex();
4697 if (getLexer().isNot(AsmToken::EndOfStatement))
4698 return reportParseError("unexpected token, expected end of statement");
4699
4700 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
4701 getTargetStreamer().emitDirectiveSetHardFloat();
4702 return false;
4703}
4704
Jack Carterd76b2372013-03-21 21:44:16 +00004705bool MipsAsmParser::parseSetAssignment() {
4706 StringRef Name;
4707 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00004708 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00004709
4710 if (Parser.parseIdentifier(Name))
4711 reportParseError("expected identifier after .set");
4712
4713 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00004714 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00004715 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00004716
Jack Carter3b2c96e2014-01-22 23:31:38 +00004717 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00004718 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00004719
Jim Grosbach6f482002015-05-18 18:43:14 +00004720 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00004721 Sym->setVariableValue(Value);
4722
4723 return false;
4724}
Jack Carterd0bd6422013-04-18 00:41:53 +00004725
Toma Tabacu26647792014-09-09 12:52:14 +00004726bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004727 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00004728 Parser.Lex();
4729 if (getLexer().isNot(AsmToken::EndOfStatement))
4730 return reportParseError("unexpected token, expected end of statement");
4731
4732 // Reset assembler options to their initial values.
Toma Tabacu465acfd2015-06-09 13:33:26 +00004733 setAvailableFeatures(
4734 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
4735 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00004736 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
4737
4738 getTargetStreamer().emitDirectiveSetMips0();
4739 return false;
4740}
4741
Toma Tabacu85618b32014-08-19 14:22:52 +00004742bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004743 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00004744 Parser.Lex();
4745 if (getLexer().isNot(AsmToken::Equal))
4746 return reportParseError("unexpected token, expected equals sign");
4747
4748 Parser.Lex();
4749 StringRef Arch;
4750 if (Parser.parseIdentifier(Arch))
4751 return reportParseError("expected arch identifier");
4752
4753 StringRef ArchFeatureName =
4754 StringSwitch<StringRef>(Arch)
4755 .Case("mips1", "mips1")
4756 .Case("mips2", "mips2")
4757 .Case("mips3", "mips3")
4758 .Case("mips4", "mips4")
4759 .Case("mips5", "mips5")
4760 .Case("mips32", "mips32")
4761 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00004762 .Case("mips32r3", "mips32r3")
4763 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00004764 .Case("mips32r6", "mips32r6")
4765 .Case("mips64", "mips64")
4766 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00004767 .Case("mips64r3", "mips64r3")
4768 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00004769 .Case("mips64r6", "mips64r6")
4770 .Case("cnmips", "cnmips")
4771 .Case("r4000", "mips3") // This is an implementation of Mips3.
4772 .Default("");
4773
4774 if (ArchFeatureName.empty())
4775 return reportParseError("unsupported architecture");
4776
4777 selectArch(ArchFeatureName);
4778 getTargetStreamer().emitDirectiveSetArch(Arch);
4779 return false;
4780}
4781
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004782bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004783 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004784 Parser.Lex();
4785 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004786 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004787
Matheus Almeida2852af82014-04-22 10:15:54 +00004788 switch (Feature) {
4789 default:
4790 llvm_unreachable("Unimplemented feature");
4791 case Mips::FeatureDSP:
4792 setFeatureBits(Mips::FeatureDSP, "dsp");
4793 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004794 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004795 case Mips::FeatureMicroMips:
4796 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004797 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004798 case Mips::FeatureMips1:
4799 selectArch("mips1");
4800 getTargetStreamer().emitDirectiveSetMips1();
4801 break;
4802 case Mips::FeatureMips2:
4803 selectArch("mips2");
4804 getTargetStreamer().emitDirectiveSetMips2();
4805 break;
4806 case Mips::FeatureMips3:
4807 selectArch("mips3");
4808 getTargetStreamer().emitDirectiveSetMips3();
4809 break;
4810 case Mips::FeatureMips4:
4811 selectArch("mips4");
4812 getTargetStreamer().emitDirectiveSetMips4();
4813 break;
4814 case Mips::FeatureMips5:
4815 selectArch("mips5");
4816 getTargetStreamer().emitDirectiveSetMips5();
4817 break;
4818 case Mips::FeatureMips32:
4819 selectArch("mips32");
4820 getTargetStreamer().emitDirectiveSetMips32();
4821 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004822 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004823 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00004824 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004825 break;
Daniel Sanders17793142015-02-18 16:24:50 +00004826 case Mips::FeatureMips32r3:
4827 selectArch("mips32r3");
4828 getTargetStreamer().emitDirectiveSetMips32R3();
4829 break;
4830 case Mips::FeatureMips32r5:
4831 selectArch("mips32r5");
4832 getTargetStreamer().emitDirectiveSetMips32R5();
4833 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004834 case Mips::FeatureMips32r6:
4835 selectArch("mips32r6");
4836 getTargetStreamer().emitDirectiveSetMips32R6();
4837 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004838 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004839 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00004840 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00004841 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004842 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004843 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00004844 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00004845 break;
Daniel Sanders17793142015-02-18 16:24:50 +00004846 case Mips::FeatureMips64r3:
4847 selectArch("mips64r3");
4848 getTargetStreamer().emitDirectiveSetMips64R3();
4849 break;
4850 case Mips::FeatureMips64r5:
4851 selectArch("mips64r5");
4852 getTargetStreamer().emitDirectiveSetMips64R5();
4853 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004854 case Mips::FeatureMips64r6:
4855 selectArch("mips64r6");
4856 getTargetStreamer().emitDirectiveSetMips64R6();
4857 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004858 }
4859 return false;
4860}
4861
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004862bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004863 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004864 if (getLexer().isNot(AsmToken::Comma)) {
4865 SMLoc Loc = getLexer().getLoc();
4866 Parser.eatToEndOfStatement();
4867 return Error(Loc, ErrorStr);
4868 }
4869
Matheus Almeida2852af82014-04-22 10:15:54 +00004870 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004871 return true;
4872}
4873
Daniel Sanderse2982ad2015-09-17 16:08:39 +00004874// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
4875// In this class, it is only used for .cprestore.
4876// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
4877// MipsTargetELFStreamer and MipsAsmParser.
4878bool MipsAsmParser::isPicAndNotNxxAbi() {
4879 return inPicMode() && !(isABI_N32() || isABI_N64());
4880}
4881
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004882bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00004883 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00004884 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004885
Toma Tabacudde4c462014-11-06 10:02:45 +00004886 if (inMips16Mode()) {
4887 reportParseError(".cpload is not supported in Mips16 mode");
4888 return false;
4889 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004890
David Blaikie960ea3f2014-06-08 16:18:35 +00004891 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00004892 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004893 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4894 reportParseError("expected register containing function address");
4895 return false;
4896 }
4897
David Blaikie960ea3f2014-06-08 16:18:35 +00004898 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
4899 if (!RegOpnd.isGPRAsmReg()) {
4900 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004901 return false;
4902 }
4903
Toma Tabacudde4c462014-11-06 10:02:45 +00004904 // If this is not the end of the statement, report an error.
4905 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4906 reportParseError("unexpected token, expected end of statement");
4907 return false;
4908 }
4909
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004910 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004911 return false;
4912}
4913
Daniel Sanderse2982ad2015-09-17 16:08:39 +00004914bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
4915 MCAsmParser &Parser = getParser();
4916
4917 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
4918 // is used in non-PIC mode.
4919
4920 if (inMips16Mode()) {
4921 reportParseError(".cprestore is not supported in Mips16 mode");
4922 return false;
4923 }
4924
4925 // Get the stack offset value.
4926 const MCExpr *StackOffset;
4927 int64_t StackOffsetVal;
4928 if (Parser.parseExpression(StackOffset)) {
4929 reportParseError("expected stack offset value");
4930 return false;
4931 }
4932
4933 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
4934 reportParseError("stack offset is not an absolute expression");
4935 return false;
4936 }
4937
4938 if (StackOffsetVal < 0) {
4939 Warning(Loc, ".cprestore with negative stack offset has no effect");
4940 IsCpRestoreSet = false;
4941 } else {
4942 IsCpRestoreSet = true;
4943 CpRestoreOffset = StackOffsetVal;
4944 }
4945
4946 // If this is not the end of the statement, report an error.
4947 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4948 reportParseError("unexpected token, expected end of statement");
4949 return false;
4950 }
4951
4952 // Store the $gp on the stack.
4953 SmallVector<MCInst, 3> StoreInsts;
4954 createCpRestoreMemOp(false /*IsLoad*/, CpRestoreOffset /*StackOffset*/, Loc,
4955 StoreInsts);
4956
4957 getTargetStreamer().emitDirectiveCpRestore(StoreInsts, CpRestoreOffset);
4958 Parser.Lex(); // Consume the EndOfStatement.
4959 return false;
4960}
4961
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004962bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004963 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004964 unsigned FuncReg;
4965 unsigned Save;
4966 bool SaveIsReg = true;
4967
Matheus Almeida7e815762014-06-18 13:08:59 +00004968 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00004969 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00004970 if (ResTy == MatchOperand_NoMatch) {
4971 reportParseError("expected register containing function address");
4972 Parser.eatToEndOfStatement();
4973 return false;
4974 }
4975
4976 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4977 if (!FuncRegOpnd.isGPRAsmReg()) {
4978 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
4979 Parser.eatToEndOfStatement();
4980 return false;
4981 }
4982
4983 FuncReg = FuncRegOpnd.getGPR32Reg();
4984 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004985
Toma Tabacu65f10572014-09-16 15:00:52 +00004986 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004987 return true;
4988
Toma Tabacu13964452014-09-04 13:23:44 +00004989 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00004990 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00004991 const MCExpr *OffsetExpr;
4992 int64_t OffsetVal;
4993 SMLoc ExprLoc = getLexer().getLoc();
4994
4995 if (Parser.parseExpression(OffsetExpr) ||
4996 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
4997 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00004998 Parser.eatToEndOfStatement();
4999 return false;
5000 }
Daniel Sanders5d796282015-09-21 09:26:55 +00005001
5002 Save = OffsetVal;
5003 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00005004 } else {
5005 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5006 if (!SaveOpnd.isGPRAsmReg()) {
5007 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
5008 Parser.eatToEndOfStatement();
5009 return false;
5010 }
5011 Save = SaveOpnd.getGPR32Reg();
5012 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005013
Toma Tabacu65f10572014-09-16 15:00:52 +00005014 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005015 return true;
5016
Toma Tabacu8874eac2015-02-18 13:46:53 +00005017 const MCExpr *Expr;
5018 if (Parser.parseExpression(Expr)) {
5019 reportParseError("expected expression");
5020 return false;
5021 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005022
Toma Tabacu8874eac2015-02-18 13:46:53 +00005023 if (Expr->getKind() != MCExpr::SymbolRef) {
5024 reportParseError("expected symbol");
5025 return false;
5026 }
5027 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
5028
Daniel Sandersf173dda2015-09-22 10:50:09 +00005029 CpSaveLocation = Save;
5030 CpSaveLocationIsRegister = SaveIsReg;
5031
Toma Tabacu8874eac2015-02-18 13:46:53 +00005032 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
5033 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005034 return false;
5035}
5036
Daniel Sandersf173dda2015-09-22 10:50:09 +00005037bool MipsAsmParser::parseDirectiveCPReturn() {
5038 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
5039 CpSaveLocationIsRegister);
5040 return false;
5041}
5042
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005043bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005044 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005045 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5046 const AsmToken &Tok = Parser.getTok();
5047
5048 if (Tok.getString() == "2008") {
5049 Parser.Lex();
5050 getTargetStreamer().emitDirectiveNaN2008();
5051 return false;
5052 } else if (Tok.getString() == "legacy") {
5053 Parser.Lex();
5054 getTargetStreamer().emitDirectiveNaNLegacy();
5055 return false;
5056 }
5057 }
5058 // If we don't recognize the option passed to the .nan
5059 // directive (e.g. no option or unknown option), emit an error.
5060 reportParseError("invalid option in .nan directive");
5061 return false;
5062}
5063
Jack Carter0b744b32012-10-04 02:29:46 +00005064bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005065 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005066 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00005067 const AsmToken &Tok = Parser.getTok();
5068
5069 if (Tok.getString() == "noat") {
5070 return parseSetNoAtDirective();
5071 } else if (Tok.getString() == "at") {
5072 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00005073 } else if (Tok.getString() == "arch") {
5074 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005075 } else if (Tok.getString() == "fp") {
5076 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005077 } else if (Tok.getString() == "oddspreg") {
5078 return parseSetOddSPRegDirective();
5079 } else if (Tok.getString() == "nooddspreg") {
5080 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005081 } else if (Tok.getString() == "pop") {
5082 return parseSetPopDirective();
5083 } else if (Tok.getString() == "push") {
5084 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00005085 } else if (Tok.getString() == "reorder") {
5086 return parseSetReorderDirective();
5087 } else if (Tok.getString() == "noreorder") {
5088 return parseSetNoReorderDirective();
5089 } else if (Tok.getString() == "macro") {
5090 return parseSetMacroDirective();
5091 } else if (Tok.getString() == "nomacro") {
5092 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00005093 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00005094 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005095 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00005096 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005097 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00005098 getTargetStreamer().emitDirectiveSetNoMicroMips();
5099 Parser.eatToEndOfStatement();
5100 return false;
5101 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005102 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00005103 } else if (Tok.getString() == "mips0") {
5104 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00005105 } else if (Tok.getString() == "mips1") {
5106 return parseSetFeature(Mips::FeatureMips1);
5107 } else if (Tok.getString() == "mips2") {
5108 return parseSetFeature(Mips::FeatureMips2);
5109 } else if (Tok.getString() == "mips3") {
5110 return parseSetFeature(Mips::FeatureMips3);
5111 } else if (Tok.getString() == "mips4") {
5112 return parseSetFeature(Mips::FeatureMips4);
5113 } else if (Tok.getString() == "mips5") {
5114 return parseSetFeature(Mips::FeatureMips5);
5115 } else if (Tok.getString() == "mips32") {
5116 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00005117 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005118 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005119 } else if (Tok.getString() == "mips32r3") {
5120 return parseSetFeature(Mips::FeatureMips32r3);
5121 } else if (Tok.getString() == "mips32r5") {
5122 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005123 } else if (Tok.getString() == "mips32r6") {
5124 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005125 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005126 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005127 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005128 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005129 } else if (Tok.getString() == "mips64r3") {
5130 return parseSetFeature(Mips::FeatureMips64r3);
5131 } else if (Tok.getString() == "mips64r5") {
5132 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005133 } else if (Tok.getString() == "mips64r6") {
5134 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00005135 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005136 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005137 } else if (Tok.getString() == "nodsp") {
5138 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00005139 } else if (Tok.getString() == "msa") {
5140 return parseSetMsaDirective();
5141 } else if (Tok.getString() == "nomsa") {
5142 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00005143 } else if (Tok.getString() == "softfloat") {
5144 return parseSetSoftFloatDirective();
5145 } else if (Tok.getString() == "hardfloat") {
5146 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00005147 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00005148 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00005149 parseSetAssignment();
5150 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005151 }
Jack Carter07c818d2013-01-25 01:31:34 +00005152
Jack Carter0b744b32012-10-04 02:29:46 +00005153 return true;
5154}
5155
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005156/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00005157/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005158bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005159 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005160 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5161 for (;;) {
5162 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005163 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00005164 return true;
5165
5166 getParser().getStreamer().EmitValue(Value, Size);
5167
5168 if (getLexer().is(AsmToken::EndOfStatement))
5169 break;
5170
Jack Carter07c818d2013-01-25 01:31:34 +00005171 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005172 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00005173 Parser.Lex();
5174 }
5175 }
5176
5177 Parser.Lex();
5178 return false;
5179}
5180
Vladimir Medic4c299852013-11-06 11:27:05 +00005181/// parseDirectiveGpWord
5182/// ::= .gpword local_sym
5183bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005184 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00005185 const MCExpr *Value;
5186 // EmitGPRel32Value requires an expression, so we are using base class
5187 // method to evaluate the expression.
5188 if (getParser().parseExpression(Value))
5189 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00005190 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00005191
Vladimir Medice10c1122013-11-13 13:18:04 +00005192 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005193 return Error(getLexer().getLoc(),
5194 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00005195 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00005196 return false;
5197}
5198
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005199/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00005200/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005201bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005202 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005203 const MCExpr *Value;
5204 // EmitGPRel64Value requires an expression, so we are using base class
5205 // method to evaluate the expression.
5206 if (getParser().parseExpression(Value))
5207 return true;
5208 getParser().getStreamer().EmitGPRel64Value(Value);
5209
5210 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005211 return Error(getLexer().getLoc(),
5212 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00005213 Parser.Lex(); // Eat EndOfStatement token.
5214 return false;
5215}
5216
Jack Carter0cd3c192014-01-06 23:27:31 +00005217bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005218 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00005219 // Get the option token.
5220 AsmToken Tok = Parser.getTok();
5221 // At the moment only identifiers are supported.
5222 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005223 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00005224 Parser.eatToEndOfStatement();
5225 return false;
5226 }
5227
5228 StringRef Option = Tok.getIdentifier();
5229
5230 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005231 // MipsAsmParser needs to know if the current PIC mode changes.
5232 IsPicEnabled = false;
5233
Jack Carter0cd3c192014-01-06 23:27:31 +00005234 getTargetStreamer().emitDirectiveOptionPic0();
5235 Parser.Lex();
5236 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5237 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005238 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005239 Parser.eatToEndOfStatement();
5240 }
5241 return false;
5242 }
5243
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005244 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005245 // MipsAsmParser needs to know if the current PIC mode changes.
5246 IsPicEnabled = true;
5247
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005248 getTargetStreamer().emitDirectiveOptionPic2();
5249 Parser.Lex();
5250 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5251 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005252 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005253 Parser.eatToEndOfStatement();
5254 }
5255 return false;
5256 }
5257
Jack Carter0cd3c192014-01-06 23:27:31 +00005258 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00005259 Warning(Parser.getTok().getLoc(),
5260 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00005261 Parser.eatToEndOfStatement();
5262 return false;
5263}
5264
Toma Tabacu9ca50962015-04-16 09:53:47 +00005265/// parseInsnDirective
5266/// ::= .insn
5267bool MipsAsmParser::parseInsnDirective() {
5268 // If this is not the end of the statement, report an error.
5269 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5270 reportParseError("unexpected token, expected end of statement");
5271 return false;
5272 }
5273
5274 // The actual label marking happens in
5275 // MipsELFStreamer::createPendingLabelRelocs().
5276 getTargetStreamer().emitDirectiveInsn();
5277
5278 getParser().Lex(); // Eat EndOfStatement token.
5279 return false;
5280}
5281
Daniel Sanders7e527422014-07-10 13:38:23 +00005282/// parseDirectiveModule
5283/// ::= .module oddspreg
5284/// ::= .module nooddspreg
5285/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00005286/// ::= .module softfloat
5287/// ::= .module hardfloat
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005288bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005289 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005290 MCAsmLexer &Lexer = getLexer();
5291 SMLoc L = Lexer.getLoc();
5292
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00005293 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005294 // TODO : get a better message.
5295 reportParseError(".module directive must appear before any code");
5296 return false;
5297 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005298
Toma Tabacuc405c822015-01-23 10:40:19 +00005299 StringRef Option;
5300 if (Parser.parseIdentifier(Option)) {
5301 reportParseError("expected .module option identifier");
5302 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005303 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005304
Toma Tabacuc405c822015-01-23 10:40:19 +00005305 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005306 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005307
Toma Tabacu3c499582015-06-25 10:56:57 +00005308 // Synchronize the abiflags information with the FeatureBits information we
5309 // changed above.
5310 getTargetStreamer().updateABIInfo(*this);
5311
5312 // If printing assembly, use the recently updated abiflags information.
5313 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5314 // emitted at the end).
5315 getTargetStreamer().emitDirectiveModuleOddSPReg();
5316
Toma Tabacuc405c822015-01-23 10:40:19 +00005317 // If this is not the end of the statement, report an error.
5318 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5319 reportParseError("unexpected token, expected end of statement");
5320 return false;
5321 }
5322
5323 return false; // parseDirectiveModule has finished successfully.
5324 } else if (Option == "nooddspreg") {
5325 if (!isABI_O32()) {
5326 Error(L, "'.module nooddspreg' requires the O32 ABI");
5327 return false;
5328 }
5329
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005330 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005331
Toma Tabacu3c499582015-06-25 10:56:57 +00005332 // Synchronize the abiflags information with the FeatureBits information we
5333 // changed above.
5334 getTargetStreamer().updateABIInfo(*this);
5335
5336 // If printing assembly, use the recently updated abiflags information.
5337 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5338 // emitted at the end).
5339 getTargetStreamer().emitDirectiveModuleOddSPReg();
5340
Toma Tabacuc405c822015-01-23 10:40:19 +00005341 // If this is not the end of the statement, report an error.
5342 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5343 reportParseError("unexpected token, expected end of statement");
5344 return false;
5345 }
5346
5347 return false; // parseDirectiveModule has finished successfully.
5348 } else if (Option == "fp") {
5349 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00005350 } else if (Option == "softfloat") {
5351 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5352
5353 // Synchronize the ABI Flags information with the FeatureBits information we
5354 // updated above.
5355 getTargetStreamer().updateABIInfo(*this);
5356
5357 // If printing assembly, use the recently updated ABI Flags information.
5358 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5359 // emitted later).
5360 getTargetStreamer().emitDirectiveModuleSoftFloat();
5361
5362 // If this is not the end of the statement, report an error.
5363 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5364 reportParseError("unexpected token, expected end of statement");
5365 return false;
5366 }
5367
5368 return false; // parseDirectiveModule has finished successfully.
5369 } else if (Option == "hardfloat") {
5370 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5371
5372 // Synchronize the ABI Flags information with the FeatureBits information we
5373 // updated above.
5374 getTargetStreamer().updateABIInfo(*this);
5375
5376 // If printing assembly, use the recently updated ABI Flags information.
5377 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5378 // emitted later).
5379 getTargetStreamer().emitDirectiveModuleHardFloat();
5380
5381 // If this is not the end of the statement, report an error.
5382 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5383 reportParseError("unexpected token, expected end of statement");
5384 return false;
5385 }
5386
5387 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00005388 } else {
5389 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
5390 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005391}
5392
5393/// parseDirectiveModuleFP
5394/// ::= =32
5395/// ::= =xx
5396/// ::= =64
5397bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005398 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005399 MCAsmLexer &Lexer = getLexer();
5400
5401 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005402 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005403 return false;
5404 }
5405 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005406
Daniel Sanders7e527422014-07-10 13:38:23 +00005407 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005408 if (!parseFpABIValue(FpABI, ".module"))
5409 return false;
5410
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005411 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005412 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005413 return false;
5414 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005415
Toma Tabacua64e5402015-06-25 12:44:38 +00005416 // Synchronize the abiflags information with the FeatureBits information we
5417 // changed above.
5418 getTargetStreamer().updateABIInfo(*this);
5419
5420 // If printing assembly, use the recently updated abiflags information.
5421 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5422 // emitted at the end).
5423 getTargetStreamer().emitDirectiveModuleFP();
5424
Daniel Sanders7e527422014-07-10 13:38:23 +00005425 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005426 return false;
5427}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005428
Daniel Sanders7e527422014-07-10 13:38:23 +00005429bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005430 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005431 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005432 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005433 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005434
5435 if (Lexer.is(AsmToken::Identifier)) {
5436 StringRef Value = Parser.getTok().getString();
5437 Parser.Lex();
5438
5439 if (Value != "xx") {
5440 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5441 return false;
5442 }
5443
5444 if (!isABI_O32()) {
5445 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
5446 return false;
5447 }
5448
Daniel Sanders7e527422014-07-10 13:38:23 +00005449 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005450 if (ModuleLevelOptions) {
5451 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5452 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5453 } else {
5454 setFeatureBits(Mips::FeatureFPXX, "fpxx");
5455 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5456 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005457 return true;
5458 }
5459
5460 if (Lexer.is(AsmToken::Integer)) {
5461 unsigned Value = Parser.getTok().getIntVal();
5462 Parser.Lex();
5463
5464 if (Value != 32 && Value != 64) {
5465 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5466 return false;
5467 }
5468
5469 if (Value == 32) {
5470 if (!isABI_O32()) {
5471 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
5472 return false;
5473 }
5474
Daniel Sanders7e527422014-07-10 13:38:23 +00005475 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005476 if (ModuleLevelOptions) {
5477 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5478 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5479 } else {
5480 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
5481 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5482 }
Toma Tabacua64e5402015-06-25 12:44:38 +00005483 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00005484 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005485 if (ModuleLevelOptions) {
5486 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5487 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5488 } else {
5489 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
5490 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
5491 }
Toma Tabacua64e5402015-06-25 12:44:38 +00005492 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005493
Daniel Sanders7e527422014-07-10 13:38:23 +00005494 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005495 }
5496
5497 return false;
5498}
5499
Jack Carter0b744b32012-10-04 02:29:46 +00005500bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005501 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005502 StringRef IDVal = DirectiveID.getString();
5503
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005504 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005505 return parseDirectiveCpLoad(DirectiveID.getLoc());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005506 if (IDVal == ".cprestore")
5507 return parseDirectiveCpRestore(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00005508 if (IDVal == ".dword") {
5509 parseDataDirective(8, DirectiveID.getLoc());
5510 return false;
5511 }
Jack Carterd0bd6422013-04-18 00:41:53 +00005512 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005513 StringRef SymbolName;
5514
5515 if (Parser.parseIdentifier(SymbolName)) {
5516 reportParseError("expected identifier after .ent");
5517 return false;
5518 }
5519
5520 // There's an undocumented extension that allows an integer to
5521 // follow the name of the procedure which AFAICS is ignored by GAS.
5522 // Example: .ent foo,2
5523 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5524 if (getLexer().isNot(AsmToken::Comma)) {
5525 // Even though we accept this undocumented extension for compatibility
5526 // reasons, the additional integer argument does not actually change
5527 // the behaviour of the '.ent' directive, so we would like to discourage
5528 // its use. We do this by not referring to the extended version in
5529 // error messages which are not directly related to its use.
5530 reportParseError("unexpected token, expected end of statement");
5531 return false;
5532 }
5533 Parser.Lex(); // Eat the comma.
5534 const MCExpr *DummyNumber;
5535 int64_t DummyNumberVal;
5536 // If the user was explicitly trying to use the extended version,
5537 // we still give helpful extension-related error messages.
5538 if (Parser.parseExpression(DummyNumber)) {
5539 reportParseError("expected number after comma");
5540 return false;
5541 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00005542 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005543 reportParseError("expected an absolute expression after comma");
5544 return false;
5545 }
5546 }
5547
5548 // If this is not the end of the statement, report an error.
5549 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5550 reportParseError("unexpected token, expected end of statement");
5551 return false;
5552 }
5553
Jim Grosbach6f482002015-05-18 18:43:14 +00005554 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005555
5556 getTargetStreamer().emitDirectiveEnt(*Sym);
5557 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005558 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00005559 return false;
5560 }
5561
Jack Carter07c818d2013-01-25 01:31:34 +00005562 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005563 StringRef SymbolName;
5564
5565 if (Parser.parseIdentifier(SymbolName)) {
5566 reportParseError("expected identifier after .end");
5567 return false;
5568 }
5569
5570 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5571 reportParseError("unexpected token, expected end of statement");
5572 return false;
5573 }
5574
5575 if (CurrentFn == nullptr) {
5576 reportParseError(".end used without .ent");
5577 return false;
5578 }
5579
5580 if ((SymbolName != CurrentFn->getName())) {
5581 reportParseError(".end symbol does not match .ent symbol");
5582 return false;
5583 }
5584
5585 getTargetStreamer().emitDirectiveEnd(SymbolName);
5586 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005587 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00005588 return false;
5589 }
5590
Jack Carter07c818d2013-01-25 01:31:34 +00005591 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005592 // .frame $stack_reg, frame_size_in_bytes, $return_reg
5593 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005594 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005595 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5596 reportParseError("expected stack register");
5597 return false;
5598 }
5599
5600 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5601 if (!StackRegOpnd.isGPRAsmReg()) {
5602 reportParseError(StackRegOpnd.getStartLoc(),
5603 "expected general purpose register");
5604 return false;
5605 }
5606 unsigned StackReg = StackRegOpnd.getGPR32Reg();
5607
5608 if (Parser.getTok().is(AsmToken::Comma))
5609 Parser.Lex();
5610 else {
5611 reportParseError("unexpected token, expected comma");
5612 return false;
5613 }
5614
5615 // Parse the frame size.
5616 const MCExpr *FrameSize;
5617 int64_t FrameSizeVal;
5618
5619 if (Parser.parseExpression(FrameSize)) {
5620 reportParseError("expected frame size value");
5621 return false;
5622 }
5623
Jim Grosbach13760bd2015-05-30 01:25:56 +00005624 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005625 reportParseError("frame size not an absolute expression");
5626 return false;
5627 }
5628
5629 if (Parser.getTok().is(AsmToken::Comma))
5630 Parser.Lex();
5631 else {
5632 reportParseError("unexpected token, expected comma");
5633 return false;
5634 }
5635
5636 // Parse the return register.
5637 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00005638 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005639 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5640 reportParseError("expected return register");
5641 return false;
5642 }
5643
5644 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5645 if (!ReturnRegOpnd.isGPRAsmReg()) {
5646 reportParseError(ReturnRegOpnd.getStartLoc(),
5647 "expected general purpose register");
5648 return false;
5649 }
5650
5651 // If this is not the end of the statement, report an error.
5652 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5653 reportParseError("unexpected token, expected end of statement");
5654 return false;
5655 }
5656
5657 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
5658 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005659 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00005660 return false;
5661 }
5662
Jack Carter07c818d2013-01-25 01:31:34 +00005663 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00005664 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00005665 }
5666
Daniel Sandersd97a6342014-08-13 10:07:34 +00005667 if (IDVal == ".mask" || IDVal == ".fmask") {
5668 // .mask bitmask, frame_offset
5669 // bitmask: One bit for each register used.
5670 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
5671 // first register is expected to be saved.
5672 // Examples:
5673 // .mask 0x80000000, -4
5674 // .fmask 0x80000000, -4
5675 //
Jack Carterbe332172012-09-07 00:48:02 +00005676
Daniel Sandersd97a6342014-08-13 10:07:34 +00005677 // Parse the bitmask
5678 const MCExpr *BitMask;
5679 int64_t BitMaskVal;
5680
5681 if (Parser.parseExpression(BitMask)) {
5682 reportParseError("expected bitmask value");
5683 return false;
5684 }
5685
Jim Grosbach13760bd2015-05-30 01:25:56 +00005686 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005687 reportParseError("bitmask not an absolute expression");
5688 return false;
5689 }
5690
5691 if (Parser.getTok().is(AsmToken::Comma))
5692 Parser.Lex();
5693 else {
5694 reportParseError("unexpected token, expected comma");
5695 return false;
5696 }
5697
5698 // Parse the frame_offset
5699 const MCExpr *FrameOffset;
5700 int64_t FrameOffsetVal;
5701
5702 if (Parser.parseExpression(FrameOffset)) {
5703 reportParseError("expected frame offset value");
5704 return false;
5705 }
5706
Jim Grosbach13760bd2015-05-30 01:25:56 +00005707 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005708 reportParseError("frame offset not an absolute expression");
5709 return false;
5710 }
5711
5712 // If this is not the end of the statement, report an error.
5713 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5714 reportParseError("unexpected token, expected end of statement");
5715 return false;
5716 }
5717
5718 if (IDVal == ".mask")
5719 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
5720 else
5721 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00005722 return false;
5723 }
5724
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005725 if (IDVal == ".nan")
5726 return parseDirectiveNaN();
5727
Jack Carter07c818d2013-01-25 01:31:34 +00005728 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00005729 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00005730 return false;
5731 }
5732
Rafael Espindolab59fb732014-03-28 18:50:26 +00005733 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005734 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005735 return false;
5736 }
5737
Jack Carter07c818d2013-01-25 01:31:34 +00005738 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005739 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00005740 return false;
5741 }
5742
Jack Carter0cd3c192014-01-06 23:27:31 +00005743 if (IDVal == ".option")
5744 return parseDirectiveOption();
5745
5746 if (IDVal == ".abicalls") {
5747 getTargetStreamer().emitDirectiveAbiCalls();
5748 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005749 Error(Parser.getTok().getLoc(),
5750 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005751 // Clear line
5752 Parser.eatToEndOfStatement();
5753 }
5754 return false;
5755 }
5756
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005757 if (IDVal == ".cpsetup")
5758 return parseDirectiveCPSetup();
5759
Daniel Sandersf173dda2015-09-22 10:50:09 +00005760 if (IDVal == ".cpreturn")
5761 return parseDirectiveCPReturn();
5762
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005763 if (IDVal == ".module")
5764 return parseDirectiveModule();
5765
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00005766 if (IDVal == ".llvm_internal_mips_reallow_module_directive")
5767 return parseInternalDirectiveReallowModule();
5768
Toma Tabacu9ca50962015-04-16 09:53:47 +00005769 if (IDVal == ".insn")
5770 return parseInsnDirective();
5771
Rafael Espindola870c4e92012-01-11 03:56:41 +00005772 return true;
5773}
5774
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00005775bool MipsAsmParser::parseInternalDirectiveReallowModule() {
5776 // If this is not the end of the statement, report an error.
5777 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5778 reportParseError("unexpected token, expected end of statement");
5779 return false;
5780 }
5781
5782 getTargetStreamer().reallowModuleDirective();
5783
5784 getParser().Lex(); // Eat EndOfStatement token.
5785 return false;
5786}
5787
Rafael Espindola870c4e92012-01-11 03:56:41 +00005788extern "C" void LLVMInitializeMipsAsmParser() {
5789 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
5790 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
5791 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
5792 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
5793}
Jack Carterb4dbc172012-09-05 23:34:03 +00005794
5795#define GET_REGISTER_MATCHER
5796#define GET_MATCHER_IMPLEMENTATION
5797#include "MipsGenAsmMatcher.inc"