blob: f47104597704ef0abc709ba233e3e9ee23f082c9 [file] [log] [blame]
Jia Liu9f610112012-02-17 08:55:11 +00001//===-- MipsAsmParser.cpp - Parse Mips assembly to MCInst instructions ----===//
Rafael Espindola870c4e92012-01-11 03:56:41 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Eric Christophera5762812015-01-26 17:33:46 +000010#include "MCTargetDesc/MipsABIInfo.h"
Petar Jovanovica5da5882014-02-04 18:41:57 +000011#include "MCTargetDesc/MipsMCExpr.h"
Rafael Espindola870c4e92012-01-11 03:56:41 +000012#include "MCTargetDesc/MipsMCTargetDesc.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000013#include "MipsRegisterInfo.h"
Daniel Sandersa6994442015-08-18 12:33:54 +000014#include "MipsTargetObjectFile.h"
Rafael Espindolaa17151a2013-10-08 13:08:17 +000015#include "MipsTargetStreamer.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000016#include "llvm/ADT/APInt.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000017#include "llvm/ADT/SmallVector.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000018#include "llvm/ADT/StringSwitch.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000019#include "llvm/MC/MCContext.h"
20#include "llvm/MC/MCExpr.h"
21#include "llvm/MC/MCInst.h"
Daniel Sandersa771fef2014-03-24 14:05:39 +000022#include "llvm/MC/MCInstBuilder.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000023#include "llvm/MC/MCParser/MCAsmLexer.h"
24#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000025#include "llvm/MC/MCStreamer.h"
26#include "llvm/MC/MCSubtargetInfo.h"
27#include "llvm/MC/MCSymbol.h"
Akira Hatanaka7605630c2012-08-17 20:16:42 +000028#include "llvm/MC/MCTargetAsmParser.h"
Daniel Sandersb50ccf82014-04-01 10:35:28 +000029#include "llvm/Support/Debug.h"
Matheus Almeidae0d75aa2013-12-13 11:11:02 +000030#include "llvm/Support/MathExtras.h"
Daniel Sandersef638fe2014-10-03 15:37:37 +000031#include "llvm/Support/SourceMgr.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000032#include "llvm/Support/TargetRegistry.h"
Benjamin Kramer799003b2015-03-23 19:32:43 +000033#include "llvm/Support/raw_ostream.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000034#include <memory>
Rafael Espindola870c4e92012-01-11 03:56:41 +000035
36using namespace llvm;
37
Chandler Carruthe96dd892014-04-21 22:55:11 +000038#define DEBUG_TYPE "mips-asm-parser"
39
Joey Gouly0e76fa72013-09-12 10:28:05 +000040namespace llvm {
41class MCInstrInfo;
42}
43
Rafael Espindola870c4e92012-01-11 03:56:41 +000044namespace {
Jack Carter0b744b32012-10-04 02:29:46 +000045class MipsAssemblerOptions {
46public:
Toma Tabacu465acfd2015-06-09 13:33:26 +000047 MipsAssemblerOptions(const FeatureBitset &Features_) :
Toma Tabacu9db22db2014-09-09 10:15:38 +000048 ATReg(1), Reorder(true), Macro(true), Features(Features_) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000049
Toma Tabacu9db22db2014-09-09 10:15:38 +000050 MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
Toma Tabacub19cf202015-04-27 13:12:59 +000051 ATReg = Opts->getATRegIndex();
Toma Tabacu9db22db2014-09-09 10:15:38 +000052 Reorder = Opts->isReorder();
53 Macro = Opts->isMacro();
54 Features = Opts->getFeatures();
55 }
56
Toma Tabacub19cf202015-04-27 13:12:59 +000057 unsigned getATRegIndex() const { return ATReg; }
58 bool setATRegIndex(unsigned Reg) {
Toma Tabacu92dbbf12015-03-26 13:08:55 +000059 if (Reg > 31)
60 return false;
61
62 ATReg = Reg;
63 return true;
64 }
Jack Carter0b744b32012-10-04 02:29:46 +000065
Toma Tabacu9db22db2014-09-09 10:15:38 +000066 bool isReorder() const { return Reorder; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000067 void setReorder() { Reorder = true; }
68 void setNoReorder() { Reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000069
Toma Tabacu9db22db2014-09-09 10:15:38 +000070 bool isMacro() const { return Macro; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000071 void setMacro() { Macro = true; }
72 void setNoMacro() { Macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000073
Toma Tabacu465acfd2015-06-09 13:33:26 +000074 const FeatureBitset &getFeatures() const { return Features; }
75 void setFeatures(const FeatureBitset &Features_) { Features = Features_; }
Toma Tabacu9db22db2014-09-09 10:15:38 +000076
Daniel Sandersf0df2212014-08-04 12:20:00 +000077 // Set of features that are either architecture features or referenced
78 // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6).
79 // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
80 // The reason we need this mask is explained in the selectArch function.
81 // FIXME: Ideally we would like TableGen to generate this information.
Michael Kupersteindb0712f2015-05-26 10:47:10 +000082 static const FeatureBitset AllArchRelatedMask;
Daniel Sandersf0df2212014-08-04 12:20:00 +000083
Jack Carter0b744b32012-10-04 02:29:46 +000084private:
Toma Tabacu3c24b042014-09-05 15:43:21 +000085 unsigned ATReg;
86 bool Reorder;
87 bool Macro;
Toma Tabacu465acfd2015-06-09 13:33:26 +000088 FeatureBitset Features;
Jack Carter0b744b32012-10-04 02:29:46 +000089};
90}
91
Michael Kupersteindb0712f2015-05-26 10:47:10 +000092const FeatureBitset MipsAssemblerOptions::AllArchRelatedMask = {
93 Mips::FeatureMips1, Mips::FeatureMips2, Mips::FeatureMips3,
94 Mips::FeatureMips3_32, Mips::FeatureMips3_32r2, Mips::FeatureMips4,
95 Mips::FeatureMips4_32, Mips::FeatureMips4_32r2, Mips::FeatureMips5,
96 Mips::FeatureMips5_32r2, Mips::FeatureMips32, Mips::FeatureMips32r2,
97 Mips::FeatureMips32r3, Mips::FeatureMips32r5, Mips::FeatureMips32r6,
98 Mips::FeatureMips64, Mips::FeatureMips64r2, Mips::FeatureMips64r3,
99 Mips::FeatureMips64r5, Mips::FeatureMips64r6, Mips::FeatureCnMips,
100 Mips::FeatureFP64Bit, Mips::FeatureGP64Bit, Mips::FeatureNaN2008
101};
102
Jack Carter0b744b32012-10-04 02:29:46 +0000103namespace {
Rafael Espindola870c4e92012-01-11 03:56:41 +0000104class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000105 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola961d4692014-11-11 05:18:41 +0000106 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000107 return static_cast<MipsTargetStreamer &>(TS);
108 }
109
Jack Carterb4dbc172012-09-05 23:34:03 +0000110 MCSubtargetInfo &STI;
Eric Christophera5762812015-01-26 17:33:46 +0000111 MipsABIInfo ABI;
Toma Tabacu9db22db2014-09-09 10:15:38 +0000112 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
Daniel Sandersd97a6342014-08-13 10:07:34 +0000113 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
114 // nullptr, which indicates that no function is currently
115 // selected. This usually happens after an '.end func'
116 // directive.
Toma Tabacud88d79c2015-06-23 14:39:42 +0000117 bool IsLittleEndian;
Daniel Sandersa6994442015-08-18 12:33:54 +0000118 bool IsPicEnabled;
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000119 bool IsCpRestoreSet;
120 int CpRestoreOffset;
Daniel Sandersf173dda2015-09-22 10:50:09 +0000121 unsigned CpSaveLocation;
122 /// If true, then CpSaveLocation is a register, otherwise it's an offset.
123 bool CpSaveLocationIsRegister;
Jack Carter0b744b32012-10-04 02:29:46 +0000124
Daniel Sandersef638fe2014-10-03 15:37:37 +0000125 // Print a warning along with its fix-it message at the given range.
126 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
127 SMRange Range, bool ShowColors = true);
128
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000129#define GET_ASSEMBLER_HEADER
130#include "MipsGenAsmMatcher.inc"
131
Matheus Almeida595fcab2014-06-11 15:05:56 +0000132 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
133
Chad Rosier49963552012-10-13 00:26:04 +0000134 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000135 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000136 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000137 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000138
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000139 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000140 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000141
Toma Tabacu13964452014-09-04 13:23:44 +0000142 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000143
Toma Tabacu13964452014-09-04 13:23:44 +0000144 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000145
David Blaikie960ea3f2014-06-08 16:18:35 +0000146 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
147 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000148
Craig Topper56c590a2014-04-29 07:58:02 +0000149 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000150
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000151 OperandMatchResultTy parseMemOperand(OperandVector &Operands);
152 OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000153 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000154 StringRef Identifier, SMLoc S);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000155 OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands,
156 SMLoc S);
157 OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
158 OperandMatchResultTy parseImm(OperandVector &Operands);
159 OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
160 OperandMatchResultTy parseInvNum(OperandVector &Operands);
161 OperandMatchResultTy parseLSAImm(OperandVector &Operands);
162 OperandMatchResultTy parseRegisterPair(OperandVector &Operands);
163 OperandMatchResultTy parseMovePRegPair(OperandVector &Operands);
164 OperandMatchResultTy parseRegisterList(OperandVector &Operands);
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000165
David Blaikie960ea3f2014-06-08 16:18:35 +0000166 bool searchSymbolAlias(OperandVector &Operands);
167
Toma Tabacu13964452014-09-04 13:23:44 +0000168 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000169
Daniel Sanders5bf6eab2015-10-26 23:50:00 +0000170 enum MacroExpanderResultTy {
171 MER_NotAMacro,
172 MER_Success,
173 MER_Fail,
174 };
Jack Carter30a59822012-10-04 04:03:53 +0000175
Matheus Almeida3813d572014-06-19 14:39:14 +0000176 // Expands assembly pseudo instructions.
Daniel Sanders5bf6eab2015-10-26 23:50:00 +0000177 MacroExpanderResultTy
178 tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
179 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000180
Toma Tabacu8f6603a2015-01-30 11:18:50 +0000181 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
182 SmallVectorImpl<MCInst> &Instructions);
183
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000184 bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000185 bool Is32BitImm, bool IsAddress, SMLoc IDLoc,
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000186 SmallVectorImpl<MCInst> &Instructions);
187
Toma Tabacuf712ede2015-06-17 14:31:51 +0000188 bool loadAndAddSymbolAddress(const MCExpr *SymExpr, unsigned DstReg,
189 unsigned SrcReg, bool Is32BitSym, SMLoc IDLoc,
190 SmallVectorImpl<MCInst> &Instructions);
Toma Tabacu674825c2015-06-16 12:16:24 +0000191
Toma Tabacu00e98672015-05-01 12:19:27 +0000192 bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000193 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000194
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000195 bool expandLoadAddress(unsigned DstReg, unsigned BaseReg,
196 const MCOperand &Offset, bool Is32BitAddress,
197 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000198
Jozef Kolek5cfebdd2015-01-21 12:39:30 +0000199 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
200 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000201
Jack Carter9e65aa32013-03-22 00:05:30 +0000202 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000203 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
204 bool isImmOpnd);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000205
206 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
207 SmallVectorImpl<MCInst> &Instructions);
208
Zoran Jovanoviccdb64562015-09-28 11:11:34 +0000209 bool expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
210 SmallVectorImpl<MCInst> &Instructions);
211
Toma Tabacue1e460d2015-06-11 10:36:10 +0000212 bool expandBranchImm(MCInst &Inst, SMLoc IDLoc,
213 SmallVectorImpl<MCInst> &Instructions);
214
Toma Tabacu1a108322015-06-17 13:20:24 +0000215 bool expandCondBranches(MCInst &Inst, SMLoc IDLoc,
216 SmallVectorImpl<MCInst> &Instructions);
217
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000218 bool expandDiv(MCInst &Inst, SMLoc IDLoc,
219 SmallVectorImpl<MCInst> &Instructions, const bool IsMips64,
220 const bool Signed);
221
Daniel Sanders6394ee52015-10-15 14:52:58 +0000222 bool expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
223 SmallVectorImpl<MCInst> &Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000224
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +0000225 bool expandUlw(MCInst &Inst, SMLoc IDLoc,
226 SmallVectorImpl<MCInst> &Instructions);
227
Toma Tabacu234482a2015-03-16 12:03:39 +0000228 void createNop(bool hasShortDelaySlot, SMLoc IDLoc,
229 SmallVectorImpl<MCInst> &Instructions);
230
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000231 void createAddu(unsigned DstReg, unsigned SrcReg, unsigned TrgReg,
Toma Tabacu0b3e9782015-06-23 14:00:54 +0000232 bool Is64Bit, SmallVectorImpl<MCInst> &Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000233
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000234 void createCpRestoreMemOp(bool IsLoad, int StackOffset, SMLoc IDLoc,
235 SmallVectorImpl<MCInst> &Instructions);
236
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000237 bool reportParseError(Twine ErrorMsg);
238 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000239
Jack Carterb5cf5902013-04-17 00:18:04 +0000240 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000241 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000242
Vladimir Medic4c299852013-11-06 11:27:05 +0000243 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000244
245 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000246 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000247 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000248 bool parseSetFeature(uint64_t Feature);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000249 bool isPicAndNotNxxAbi(); // Used by .cpload, .cprestore, and .cpsetup.
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000250 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000251 bool parseDirectiveCpRestore(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000252 bool parseDirectiveCPSetup();
Daniel Sandersf173dda2015-09-22 10:50:09 +0000253 bool parseDirectiveCPReturn();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000254 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000255 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000256 bool parseDirectiveOption();
Toma Tabacu9ca50962015-04-16 09:53:47 +0000257 bool parseInsnDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000258
259 bool parseSetAtDirective();
260 bool parseSetNoAtDirective();
261 bool parseSetMacroDirective();
262 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000263 bool parseSetMsaDirective();
264 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000265 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000266 bool parseSetReorderDirective();
267 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000268 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000269 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000270 bool parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +0000271 bool parseSetOddSPRegDirective();
272 bool parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000273 bool parseSetPopDirective();
274 bool parseSetPushDirective();
Toma Tabacu29696502015-06-02 09:48:04 +0000275 bool parseSetSoftFloatDirective();
276 bool parseSetHardFloatDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000277
Jack Carterd76b2372013-03-21 21:44:16 +0000278 bool parseSetAssignment();
279
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000280 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000281 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000282 bool parseDirectiveGpDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000283 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000284 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000285 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
286 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000287
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000288 bool parseInternalDirectiveReallowModule();
289
Jack Carterdc1e35d2012-09-06 20:00:02 +0000290 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000291
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000292 bool eatComma(StringRef ErrorStr);
293
Jack Carter1ac53222013-02-20 23:11:17 +0000294 int matchCPURegisterName(StringRef Symbol);
295
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000296 int matchHWRegsRegisterName(StringRef Symbol);
297
Jack Carter873c7242013-01-12 01:03:14 +0000298 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000299
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000300 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000301
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000302 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000303
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000304 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000305
Jack Carter5dc8ac92013-09-25 23:50:44 +0000306 int matchMSA128RegisterName(StringRef Name);
307
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000308 int matchMSA128CtrlRegisterName(StringRef Name);
309
Jack Carterd0bd6422013-04-18 00:41:53 +0000310 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000311
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000312 unsigned getGPR(int RegNo);
313
Toma Tabacu89a712b2015-04-15 10:48:56 +0000314 /// Returns the internal register number for the current AT. Also checks if
315 /// the current AT is unavailable (set to $0) and gives an error if it is.
316 /// This should be used in pseudo-instruction expansions which need AT.
317 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000318
319 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000320 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000321
322 // Helper function that checks if the value of a vector index is within the
323 // boundaries of accepted values for each RegisterKind
324 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
325 bool validateMSAIndex(int Val, int RegKind);
326
Daniel Sandersf0df2212014-08-04 12:20:00 +0000327 // Selects a new architecture by updating the FeatureBits with the necessary
328 // info including implied dependencies.
329 // Internally, it clears all the feature bits related to *any* architecture
330 // and selects the new one using the ToggleFeature functionality of the
331 // MCSubtargetInfo object that handles implied dependencies. The reason we
332 // clear all the arch related bits manually is because ToggleFeature only
333 // clears the features that imply the feature being cleared and not the
334 // features implied by the feature being cleared. This is easier to see
335 // with an example:
336 // --------------------------------------------------
337 // | Feature | Implies |
338 // | -------------------------------------------------|
339 // | FeatureMips1 | None |
340 // | FeatureMips2 | FeatureMips1 |
341 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
342 // | FeatureMips4 | FeatureMips3 |
343 // | ... | |
344 // --------------------------------------------------
345 //
346 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
347 // FeatureMipsGP64 | FeatureMips1)
348 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
349 void selectArch(StringRef ArchFeature) {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000350 FeatureBitset FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000351 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
352 STI.setFeatureBits(FeatureBits);
353 setAvailableFeatures(
354 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000355 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000356 }
357
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000358 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000359 if (!(STI.getFeatureBits()[Feature])) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000360 setAvailableFeatures(
361 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000362 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000363 }
364 }
365
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000366 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000367 if (STI.getFeatureBits()[Feature]) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000368 setAvailableFeatures(
369 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000370 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000371 }
372 }
373
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000374 void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
375 setFeatureBits(Feature, FeatureString);
376 AssemblerOptions.front()->setFeatures(STI.getFeatureBits());
377 }
378
379 void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
380 clearFeatureBits(Feature, FeatureString);
381 AssemblerOptions.front()->setFeatures(STI.getFeatureBits());
382 }
383
Rafael Espindola870c4e92012-01-11 03:56:41 +0000384public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000385 enum MipsMatchResultTy {
Daniel Sanders52da7af2015-11-06 12:11:03 +0000386 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY,
Matheus Almeida595fcab2014-06-11 15:05:56 +0000387#define GET_OPERAND_DIAGNOSTIC_TYPES
388#include "MipsGenAsmMatcher.inc"
389#undef GET_OPERAND_DIAGNOSTIC_TYPES
Matheus Almeida595fcab2014-06-11 15:05:56 +0000390 };
391
Joey Gouly0e76fa72013-09-12 10:28:05 +0000392 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000393 const MCInstrInfo &MII, const MCTargetOptions &Options)
Colin LeMahieufe2c8b82015-07-27 21:56:53 +0000394 : MCTargetAsmParser(Options), STI(sti),
Daniel Sanders50f17232015-09-15 16:17:27 +0000395 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
396 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000397 MCAsmParserExtension::Initialize(parser);
398
Toma Tabacu11e14a92015-04-21 11:50:52 +0000399 parser.addAliasForDirective(".asciiz", ".asciz");
400
Jack Carterb4dbc172012-09-05 23:34:03 +0000401 // Initialize the set of available features.
402 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000403
Toma Tabacu9db22db2014-09-09 10:15:38 +0000404 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000405 AssemblerOptions.push_back(
Toma Tabacu465acfd2015-06-09 13:33:26 +0000406 llvm::make_unique<MipsAssemblerOptions>(STI.getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000407
Toma Tabacu9db22db2014-09-09 10:15:38 +0000408 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000409 AssemblerOptions.push_back(
Toma Tabacu465acfd2015-06-09 13:33:26 +0000410 llvm::make_unique<MipsAssemblerOptions>(STI.getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000411
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000412 getTargetStreamer().updateABIInfo(*this);
413
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000414 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000415 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000416
417 CurrentFn = nullptr;
Toma Tabacud88d79c2015-06-23 14:39:42 +0000418
Daniel Sandersa6994442015-08-18 12:33:54 +0000419 IsPicEnabled =
420 (getContext().getObjectFileInfo()->getRelocM() == Reloc::PIC_);
421
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000422 IsCpRestoreSet = false;
423 CpRestoreOffset = -1;
424
Daniel Sanders50f17232015-09-15 16:17:27 +0000425 Triple TheTriple(sti.getTargetTriple());
426 if ((TheTriple.getArch() == Triple::mips) ||
427 (TheTriple.getArch() == Triple::mips64))
Toma Tabacud88d79c2015-06-23 14:39:42 +0000428 IsLittleEndian = false;
429 else
430 IsLittleEndian = true;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000431 }
432
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000433 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
434 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
435
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000436 bool isGP64bit() const { return STI.getFeatureBits()[Mips::FeatureGP64Bit]; }
437 bool isFP64bit() const { return STI.getFeatureBits()[Mips::FeatureFP64Bit]; }
Eric Christophera5762812015-01-26 17:33:46 +0000438 const MipsABIInfo &getABI() const { return ABI; }
439 bool isABI_N32() const { return ABI.IsN32(); }
440 bool isABI_N64() const { return ABI.IsN64(); }
441 bool isABI_O32() const { return ABI.IsO32(); }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000442 bool isABI_FPXX() const { return STI.getFeatureBits()[Mips::FeatureFPXX]; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000443
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000444 bool useOddSPReg() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000445 return !(STI.getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000446 }
447
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000448 bool inMicroMipsMode() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000449 return STI.getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000450 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000451 bool hasMips1() const { return STI.getFeatureBits()[Mips::FeatureMips1]; }
452 bool hasMips2() const { return STI.getFeatureBits()[Mips::FeatureMips2]; }
453 bool hasMips3() const { return STI.getFeatureBits()[Mips::FeatureMips3]; }
454 bool hasMips4() const { return STI.getFeatureBits()[Mips::FeatureMips4]; }
455 bool hasMips5() const { return STI.getFeatureBits()[Mips::FeatureMips5]; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000456 bool hasMips32() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000457 return STI.getFeatureBits()[Mips::FeatureMips32];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000458 }
459 bool hasMips64() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000460 return STI.getFeatureBits()[Mips::FeatureMips64];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000461 }
462 bool hasMips32r2() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000463 return STI.getFeatureBits()[Mips::FeatureMips32r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000464 }
465 bool hasMips64r2() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000466 return STI.getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000467 }
Daniel Sanders17793142015-02-18 16:24:50 +0000468 bool hasMips32r3() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000469 return (STI.getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000470 }
471 bool hasMips64r3() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000472 return (STI.getFeatureBits()[Mips::FeatureMips64r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000473 }
474 bool hasMips32r5() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000475 return (STI.getFeatureBits()[Mips::FeatureMips32r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000476 }
477 bool hasMips64r5() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000478 return (STI.getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000479 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000480 bool hasMips32r6() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000481 return STI.getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000482 }
483 bool hasMips64r6() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000484 return STI.getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000485 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000486
487 bool hasDSP() const { return STI.getFeatureBits()[Mips::FeatureDSP]; }
488 bool hasDSPR2() const { return STI.getFeatureBits()[Mips::FeatureDSPR2]; }
Zoran Jovanovic2e386d32015-10-12 16:07:25 +0000489 bool hasDSPR3() const { return STI.getFeatureBits()[Mips::FeatureDSPR3]; }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000490 bool hasMSA() const { return STI.getFeatureBits()[Mips::FeatureMSA]; }
Kai Nackee0245392015-01-27 19:11:28 +0000491 bool hasCnMips() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000492 return (STI.getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000493 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000494
Daniel Sandersa6994442015-08-18 12:33:54 +0000495 bool inPicMode() {
496 return IsPicEnabled;
497 }
498
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000499 bool inMips16Mode() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000500 return STI.getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000501 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000502
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000503 bool useTraps() const {
504 return STI.getFeatureBits()[Mips::FeatureUseTCCInDIV];
505 }
506
Eric Christophere8ae3e32015-05-07 23:10:21 +0000507 bool useSoftFloat() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000508 return STI.getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000509 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000510
Toma Tabacud9d344b2015-04-27 14:05:04 +0000511 /// Warn if RegIndex is the same as the current AT.
512 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000513
514 void warnIfNoMacro(SMLoc Loc);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000515
516 bool isLittle() const { return IsLittleEndian; }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000517};
518}
519
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000520namespace {
521
522/// MipsOperand - Instances of this class represent a parsed Mips machine
523/// instruction.
524class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000525public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000526 /// Broad categories of register classes
527 /// The exact class is finalized by the render method.
528 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000529 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000530 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000531 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000532 RegKind_FCC = 4, /// FCC
533 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
534 RegKind_MSACtrl = 16, /// MSA control registers
535 RegKind_COP2 = 32, /// COP2
536 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
537 /// context).
538 RegKind_CCR = 128, /// CCR
539 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000540 RegKind_COP3 = 512, /// COP3
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000541 RegKind_COP0 = 1024, /// COP0
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000542 /// Potentially any (e.g. $1)
543 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
544 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000545 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
Jack Carter873c7242013-01-12 01:03:14 +0000546 };
547
548private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000549 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000550 k_Immediate, /// An immediate (possibly involving symbol references)
551 k_Memory, /// Base + Offset Memory Address
552 k_PhysRegister, /// A physical register from the Mips namespace
553 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000554 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000555 k_RegList, /// A physical register list
556 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000557 } Kind;
558
David Blaikie960ea3f2014-06-08 16:18:35 +0000559public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000560 MipsOperand(KindTy K, MipsAsmParser &Parser)
561 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
562
David Blaikie960ea3f2014-06-08 16:18:35 +0000563private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000564 /// For diagnostics, and checking the assembler temporary
565 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000566
Eric Christopher8996c5d2013-03-15 00:42:55 +0000567 struct Token {
568 const char *Data;
569 unsigned Length;
570 };
571
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000572 struct PhysRegOp {
573 unsigned Num; /// Register Number
574 };
575
576 struct RegIdxOp {
577 unsigned Index; /// Index into the register class
578 RegKind Kind; /// Bitfield of the kinds it could possibly be
579 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000580 };
581
582 struct ImmOp {
583 const MCExpr *Val;
584 };
585
586 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000587 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000588 const MCExpr *Off;
589 };
590
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000591 struct RegListOp {
592 SmallVector<unsigned, 10> *List;
593 };
594
Jack Carterb4dbc172012-09-05 23:34:03 +0000595 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000596 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000597 struct PhysRegOp PhysReg;
598 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000599 struct ImmOp Imm;
600 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000601 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000602 };
603
604 SMLoc StartLoc, EndLoc;
605
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000606 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000607 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
608 const MCRegisterInfo *RegInfo,
609 SMLoc S, SMLoc E,
610 MipsAsmParser &Parser) {
611 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000612 Op->RegIdx.Index = Index;
613 Op->RegIdx.RegInfo = RegInfo;
614 Op->RegIdx.Kind = RegKind;
615 Op->StartLoc = S;
616 Op->EndLoc = E;
617 return Op;
618 }
619
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000620public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000621 /// Coerce the register to GPR32 and return the real register for the current
622 /// target.
623 unsigned getGPR32Reg() const {
624 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000625 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000626 unsigned ClassID = Mips::GPR32RegClassID;
627 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000628 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000629
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000630 /// Coerce the register to GPR32 and return the real register for the current
631 /// target.
632 unsigned getGPRMM16Reg() const {
633 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
634 unsigned ClassID = Mips::GPR32RegClassID;
635 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
636 }
637
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000638 /// Coerce the register to GPR64 and return the real register for the current
639 /// target.
640 unsigned getGPR64Reg() const {
641 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
642 unsigned ClassID = Mips::GPR64RegClassID;
643 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000644 }
645
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000646private:
647 /// Coerce the register to AFGR64 and return the real register for the current
648 /// target.
649 unsigned getAFGR64Reg() const {
650 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
651 if (RegIdx.Index % 2 != 0)
652 AsmParser.Warning(StartLoc, "Float register should be even.");
653 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
654 .getRegister(RegIdx.Index / 2);
655 }
656
657 /// Coerce the register to FGR64 and return the real register for the current
658 /// target.
659 unsigned getFGR64Reg() const {
660 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
661 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
662 .getRegister(RegIdx.Index);
663 }
664
665 /// Coerce the register to FGR32 and return the real register for the current
666 /// target.
667 unsigned getFGR32Reg() const {
668 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
669 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
670 .getRegister(RegIdx.Index);
671 }
672
673 /// Coerce the register to FGRH32 and return the real register for the current
674 /// target.
675 unsigned getFGRH32Reg() const {
676 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
677 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
678 .getRegister(RegIdx.Index);
679 }
680
681 /// Coerce the register to FCC and return the real register for the current
682 /// target.
683 unsigned getFCCReg() const {
684 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
685 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
686 .getRegister(RegIdx.Index);
687 }
688
689 /// Coerce the register to MSA128 and return the real register for the current
690 /// target.
691 unsigned getMSA128Reg() const {
692 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
693 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
694 // identical
695 unsigned ClassID = Mips::MSA128BRegClassID;
696 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
697 }
698
699 /// Coerce the register to MSACtrl and return the real register for the
700 /// current target.
701 unsigned getMSACtrlReg() const {
702 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
703 unsigned ClassID = Mips::MSACtrlRegClassID;
704 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
705 }
706
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000707 /// Coerce the register to COP0 and return the real register for the
708 /// current target.
709 unsigned getCOP0Reg() const {
710 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");
711 unsigned ClassID = Mips::COP0RegClassID;
712 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
713 }
714
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000715 /// Coerce the register to COP2 and return the real register for the
716 /// current target.
717 unsigned getCOP2Reg() const {
718 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
719 unsigned ClassID = Mips::COP2RegClassID;
720 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
721 }
722
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000723 /// Coerce the register to COP3 and return the real register for the
724 /// current target.
725 unsigned getCOP3Reg() const {
726 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
727 unsigned ClassID = Mips::COP3RegClassID;
728 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
729 }
730
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000731 /// Coerce the register to ACC64DSP and return the real register for the
732 /// current target.
733 unsigned getACC64DSPReg() const {
734 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
735 unsigned ClassID = Mips::ACC64DSPRegClassID;
736 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
737 }
738
739 /// Coerce the register to HI32DSP and return the real register for the
740 /// current target.
741 unsigned getHI32DSPReg() const {
742 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
743 unsigned ClassID = Mips::HI32DSPRegClassID;
744 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
745 }
746
747 /// Coerce the register to LO32DSP and return the real register for the
748 /// current target.
749 unsigned getLO32DSPReg() const {
750 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
751 unsigned ClassID = Mips::LO32DSPRegClassID;
752 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
753 }
754
755 /// Coerce the register to CCR and return the real register for the
756 /// current target.
757 unsigned getCCRReg() const {
758 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
759 unsigned ClassID = Mips::CCRRegClassID;
760 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
761 }
762
763 /// Coerce the register to HWRegs and return the real register for the
764 /// current target.
765 unsigned getHWRegsReg() const {
766 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
767 unsigned ClassID = Mips::HWRegsRegClassID;
768 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
769 }
770
771public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000772 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000773 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000774 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000775 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000776 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000777 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000778 else
Jim Grosbache9119e42015-05-13 18:37:00 +0000779 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000780 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000781
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000782 void addRegOperands(MCInst &Inst, unsigned N) const {
783 llvm_unreachable("Use a custom parser instead");
784 }
785
Daniel Sanders21bce302014-04-01 12:35:23 +0000786 /// Render the operand to an MCInst as a GPR32
787 /// Asserts if the wrong number of operands are requested, or the operand
788 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000789 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
790 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000791 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000792 }
793
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000794 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
795 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000796 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000797 }
798
Jozef Kolek1904fa22014-11-24 14:25:53 +0000799 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
800 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000801 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +0000802 }
803
Zoran Jovanovic41688672015-02-10 16:36:20 +0000804 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
805 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000806 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000807 }
808
Daniel Sanders21bce302014-04-01 12:35:23 +0000809 /// Render the operand to an MCInst as a GPR64
810 /// Asserts if the wrong number of operands are requested, or the operand
811 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000812 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
813 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000814 Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000815 }
816
817 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
818 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000819 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000820 }
821
822 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
823 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000824 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000825 }
826
827 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
828 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000829 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000830 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000831 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000832 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
833 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000834 }
835
836 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
837 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000838 Inst.addOperand(MCOperand::createReg(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000839 }
840
841 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
842 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000843 Inst.addOperand(MCOperand::createReg(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000844 }
845
846 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
847 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000848 Inst.addOperand(MCOperand::createReg(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000849 }
850
851 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
852 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000853 Inst.addOperand(MCOperand::createReg(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000854 }
855
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000856 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
857 assert(N == 1 && "Invalid number of operands!");
858 Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
859 }
860
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000861 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
862 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000863 Inst.addOperand(MCOperand::createReg(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000864 }
865
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000866 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
867 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000868 Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000869 }
870
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000871 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
872 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000873 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000874 }
875
876 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
877 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000878 Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000879 }
880
881 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
882 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000883 Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000884 }
885
886 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
887 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000888 Inst.addOperand(MCOperand::createReg(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000889 }
890
891 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
892 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000893 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000894 }
895
Daniel Sandersea4f6532015-11-06 12:22:31 +0000896 template <unsigned Bits, int Offset = 0>
Daniel Sanders52da7af2015-11-06 12:11:03 +0000897 void addConstantUImmOperands(MCInst &Inst, unsigned N) const {
898 assert(N == 1 && "Invalid number of operands!");
Daniel Sandersea4f6532015-11-06 12:22:31 +0000899 uint64_t Imm = getConstantImm() - Offset;
900 Imm &= (1 << Bits) - 1;
901 Imm += Offset;
Daniel Sanders52da7af2015-11-06 12:11:03 +0000902 Inst.addOperand(MCOperand::createImm(Imm));
903 }
904
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000905 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000906 assert(N == 1 && "Invalid number of operands!");
907 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000908 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000909 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000910
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000911 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000912 assert(N == 2 && "Invalid number of operands!");
913
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000914 Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
915 ? getMemBase()->getGPR64Reg()
916 : getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000917
918 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000919 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000920 }
921
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000922 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
923 assert(N == 2 && "Invalid number of operands!");
924
Jim Grosbache9119e42015-05-13 18:37:00 +0000925 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000926
927 const MCExpr *Expr = getMemOff();
928 addExpr(Inst, Expr);
929 }
930
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000931 void addRegListOperands(MCInst &Inst, unsigned N) const {
932 assert(N == 1 && "Invalid number of operands!");
933
934 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000935 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000936 }
937
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000938 void addRegPairOperands(MCInst &Inst, unsigned N) const {
939 assert(N == 2 && "Invalid number of operands!");
940 unsigned RegNo = getRegPair();
Jim Grosbache9119e42015-05-13 18:37:00 +0000941 Inst.addOperand(MCOperand::createReg(RegNo++));
942 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000943 }
944
Zoran Jovanovic41688672015-02-10 16:36:20 +0000945 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
946 assert(N == 2 && "Invalid number of operands!");
947 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000948 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000949 }
950
Craig Topper56c590a2014-04-29 07:58:02 +0000951 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000952 // As a special case until we sort out the definition of div/divu, pretend
953 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
954 if (isGPRAsmReg() && RegIdx.Index == 0)
955 return true;
956
957 return Kind == k_PhysRegister;
958 }
959 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000960 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000961 bool isConstantImm() const {
962 return isImm() && dyn_cast<MCConstantExpr>(getImm());
963 }
Daniel Sanders52da7af2015-11-06 12:11:03 +0000964 bool isConstantImmz() const {
965 return isConstantImm() && getConstantImm() == 0;
966 }
Daniel Sandersea4f6532015-11-06 12:22:31 +0000967 template <unsigned Bits, int Offset = 0> bool isConstantUImm() const {
968 return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset);
969 }
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +0000970 template <unsigned Bits> bool isUImm() const {
971 return isImm() && isConstantImm() && isUInt<Bits>(getConstantImm());
972 }
Craig Topper56c590a2014-04-29 07:58:02 +0000973 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000974 // Note: It's not possible to pretend that other operand kinds are tokens.
975 // The matcher emitter checks tokens first.
976 return Kind == k_Token;
977 }
Craig Topper56c590a2014-04-29 07:58:02 +0000978 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000979 bool isConstantMemOff() const {
980 return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
981 }
982 template <unsigned Bits> bool isMemWithSimmOffset() const {
Zoran Jovanovica6593ff2015-08-18 12:53:08 +0000983 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
984 && getMemBase()->isGPRAsmReg();
985 }
Zoran Jovanovic6e6a2c92015-09-16 09:14:35 +0000986 template <unsigned Bits> bool isMemWithSimmOffsetGPR() const {
987 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff()) &&
988 getMemBase()->isGPRAsmReg();
989 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000990 bool isMemWithGRPMM16Base() const {
991 return isMem() && getMemBase()->isMM16AsmReg();
992 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000993 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
994 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
995 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
996 }
Jozef Kolek12c69822014-12-23 16:16:33 +0000997 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
998 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
999 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1000 && (getMemBase()->getGPR32Reg() == Mips::SP);
1001 }
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00001002 bool isUImm5Lsl2() const {
1003 return (isImm() && isConstantImm() && isShiftedUInt<5, 2>(getConstantImm()));
1004 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001005 bool isRegList16() const {
1006 if (!isRegList())
1007 return false;
1008
1009 int Size = RegList.List->size();
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001010 if (Size < 2 || Size > 5)
1011 return false;
1012
1013 unsigned R0 = RegList.List->front();
1014 unsigned R1 = RegList.List->back();
1015 if (!((R0 == Mips::S0 && R1 == Mips::RA) ||
1016 (R0 == Mips::S0_64 && R1 == Mips::RA_64)))
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001017 return false;
1018
1019 int PrevReg = *RegList.List->begin();
1020 for (int i = 1; i < Size - 1; i++) {
1021 int Reg = (*(RegList.List))[i];
1022 if ( Reg != PrevReg + 1)
1023 return false;
1024 PrevReg = Reg;
1025 }
1026
1027 return true;
1028 }
Vladimir Medic2b953d02013-10-01 09:48:56 +00001029 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001030 bool isLSAImm() const {
1031 if (!isConstantImm())
1032 return false;
1033 int64_t Val = getConstantImm();
1034 return 1 <= Val && Val <= 4;
1035 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001036 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001037 bool isMovePRegPair() const {
1038 if (Kind != k_RegList || RegList.List->size() != 2)
1039 return false;
1040
1041 unsigned R0 = RegList.List->front();
1042 unsigned R1 = RegList.List->back();
1043
1044 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
1045 (R0 == Mips::A1 && R1 == Mips::A3) ||
1046 (R0 == Mips::A2 && R1 == Mips::A3) ||
1047 (R0 == Mips::A0 && R1 == Mips::S5) ||
1048 (R0 == Mips::A0 && R1 == Mips::S6) ||
1049 (R0 == Mips::A0 && R1 == Mips::A1) ||
1050 (R0 == Mips::A0 && R1 == Mips::A2) ||
1051 (R0 == Mips::A0 && R1 == Mips::A3))
1052 return true;
1053
1054 return false;
1055 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001056
1057 StringRef getToken() const {
1058 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001059 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001060 }
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001061 bool isRegPair() const { return Kind == k_RegPair; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001062
Craig Topper56c590a2014-04-29 07:58:02 +00001063 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001064 // As a special case until we sort out the definition of div/divu, pretend
1065 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
1066 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1067 RegIdx.Kind & RegKind_GPR)
1068 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001069
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001070 assert(Kind == k_PhysRegister && "Invalid access!");
1071 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +00001072 }
1073
Jack Carterb4dbc172012-09-05 23:34:03 +00001074 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001075 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001076 return Imm.Val;
1077 }
1078
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001079 int64_t getConstantImm() const {
1080 const MCExpr *Val = getImm();
1081 return static_cast<const MCConstantExpr *>(Val)->getValue();
1082 }
1083
1084 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001085 assert((Kind == k_Memory) && "Invalid access!");
1086 return Mem.Base;
1087 }
1088
1089 const MCExpr *getMemOff() const {
1090 assert((Kind == k_Memory) && "Invalid access!");
1091 return Mem.Off;
1092 }
1093
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001094 int64_t getConstantMemOff() const {
1095 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1096 }
1097
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001098 const SmallVectorImpl<unsigned> &getRegList() const {
1099 assert((Kind == k_RegList) && "Invalid access!");
1100 return *(RegList.List);
1101 }
1102
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001103 unsigned getRegPair() const {
1104 assert((Kind == k_RegPair) && "Invalid access!");
1105 return RegIdx.Index;
1106 }
1107
David Blaikie960ea3f2014-06-08 16:18:35 +00001108 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1109 MipsAsmParser &Parser) {
1110 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001111 Op->Tok.Data = Str.data();
1112 Op->Tok.Length = Str.size();
1113 Op->StartLoc = S;
1114 Op->EndLoc = S;
1115 return Op;
1116 }
1117
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001118 /// Create a numeric register (e.g. $1). The exact register remains
1119 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001120 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001121 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001122 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001123 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001124 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001125 }
1126
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001127 /// Create a register that is definitely a GPR.
1128 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001129 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001130 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001131 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001132 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001133 }
1134
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001135 /// Create a register that is definitely a FGR.
1136 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001137 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001138 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001139 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001140 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
1141 }
1142
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001143 /// Create a register that is definitely a HWReg.
1144 /// This is typically only used for named registers such as $hwr_cpunum.
1145 static std::unique_ptr<MipsOperand>
1146 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
1147 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1148 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
1149 }
1150
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001151 /// Create a register that is definitely an FCC.
1152 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001153 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001154 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001155 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001156 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
1157 }
1158
1159 /// Create a register that is definitely an ACC.
1160 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001161 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001162 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001163 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001164 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
1165 }
1166
1167 /// Create a register that is definitely an MSA128.
1168 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001169 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001170 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001171 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001172 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
1173 }
1174
1175 /// Create a register that is definitely an MSACtrl.
1176 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001177 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001178 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001179 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001180 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
1181 }
1182
David Blaikie960ea3f2014-06-08 16:18:35 +00001183 static std::unique_ptr<MipsOperand>
1184 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1185 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001186 Op->Imm.Val = Val;
1187 Op->StartLoc = S;
1188 Op->EndLoc = E;
1189 return Op;
1190 }
1191
David Blaikie960ea3f2014-06-08 16:18:35 +00001192 static std::unique_ptr<MipsOperand>
1193 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1194 SMLoc E, MipsAsmParser &Parser) {
1195 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1196 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001197 Op->Mem.Off = Off;
1198 Op->StartLoc = S;
1199 Op->EndLoc = E;
1200 return Op;
1201 }
1202
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001203 static std::unique_ptr<MipsOperand>
1204 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1205 MipsAsmParser &Parser) {
1206 assert (Regs.size() > 0 && "Empty list not allowed");
1207
1208 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001209 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001210 Op->StartLoc = StartLoc;
1211 Op->EndLoc = EndLoc;
1212 return Op;
1213 }
1214
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001215 static std::unique_ptr<MipsOperand>
1216 CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1217 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
1218 Op->RegIdx.Index = RegNo;
1219 Op->StartLoc = S;
1220 Op->EndLoc = E;
1221 return Op;
1222 }
1223
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001224 bool isGPRAsmReg() const {
1225 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001226 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001227 bool isMM16AsmReg() const {
1228 if (!(isRegIdx() && RegIdx.Kind))
1229 return false;
1230 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1231 || RegIdx.Index == 16 || RegIdx.Index == 17);
1232 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001233 bool isMM16AsmRegZero() const {
1234 if (!(isRegIdx() && RegIdx.Kind))
1235 return false;
1236 return (RegIdx.Index == 0 ||
1237 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1238 RegIdx.Index == 17);
1239 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001240 bool isMM16AsmRegMoveP() const {
1241 if (!(isRegIdx() && RegIdx.Kind))
1242 return false;
1243 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1244 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1245 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001246 bool isFGRAsmReg() const {
1247 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1248 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001249 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001250 bool isHWRegsAsmReg() const {
1251 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001252 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001253 bool isCCRAsmReg() const {
1254 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001255 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001256 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001257 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1258 return false;
1259 if (!AsmParser.hasEightFccRegisters())
1260 return RegIdx.Index == 0;
1261 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001262 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001263 bool isACCAsmReg() const {
1264 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001265 }
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001266 bool isCOP0AsmReg() const {
1267 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1268 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001269 bool isCOP2AsmReg() const {
1270 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001271 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001272 bool isCOP3AsmReg() const {
1273 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1274 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001275 bool isMSA128AsmReg() const {
1276 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001277 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001278 bool isMSACtrlAsmReg() const {
1279 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001280 }
1281
Jack Carterb4dbc172012-09-05 23:34:03 +00001282 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001283 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001284 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001285 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001286
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001287 virtual ~MipsOperand() {
1288 switch (Kind) {
1289 case k_Immediate:
1290 break;
1291 case k_Memory:
1292 delete Mem.Base;
1293 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001294 case k_RegList:
1295 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001296 case k_PhysRegister:
1297 case k_RegisterIndex:
1298 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001299 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001300 break;
1301 }
1302 }
1303
Craig Topper56c590a2014-04-29 07:58:02 +00001304 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001305 switch (Kind) {
1306 case k_Immediate:
1307 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001308 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001309 OS << ">";
1310 break;
1311 case k_Memory:
1312 OS << "Mem<";
1313 Mem.Base->print(OS);
1314 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001315 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001316 OS << ">";
1317 break;
1318 case k_PhysRegister:
1319 OS << "PhysReg<" << PhysReg.Num << ">";
1320 break;
1321 case k_RegisterIndex:
1322 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1323 break;
1324 case k_Token:
1325 OS << Tok.Data;
1326 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001327 case k_RegList:
1328 OS << "RegList< ";
1329 for (auto Reg : (*RegList.List))
1330 OS << Reg << " ";
1331 OS << ">";
1332 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001333 case k_RegPair:
1334 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1335 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001336 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001337 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001338}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001339} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001340
Jack Carter9e65aa32013-03-22 00:05:30 +00001341namespace llvm {
1342extern const MCInstrDesc MipsInsts[];
1343}
1344static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1345 return MipsInsts[Opcode];
1346}
1347
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001348static bool hasShortDelaySlot(unsigned Opcode) {
1349 switch (Opcode) {
1350 case Mips::JALS_MM:
1351 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001352 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001353 case Mips::BGEZALS_MM:
1354 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001355 return true;
1356 default:
1357 return false;
1358 }
1359}
1360
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001361static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1362 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1363 return &SRExpr->getSymbol();
1364 }
1365
1366 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1367 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1368 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1369
1370 if (LHSSym)
1371 return LHSSym;
1372
1373 if (RHSSym)
1374 return RHSSym;
1375
1376 return nullptr;
1377 }
1378
1379 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1380 return getSingleMCSymbol(UExpr->getSubExpr());
1381
1382 return nullptr;
1383}
1384
1385static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1386 if (isa<MCSymbolRefExpr>(Expr))
1387 return 1;
1388
1389 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1390 return countMCSymbolRefExpr(BExpr->getLHS()) +
1391 countMCSymbolRefExpr(BExpr->getRHS());
1392
1393 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1394 return countMCSymbolRefExpr(UExpr->getSubExpr());
1395
1396 return 0;
1397}
1398
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001399namespace {
1400void emitRX(unsigned Opcode, unsigned Reg0, MCOperand Op1, SMLoc IDLoc,
1401 SmallVectorImpl<MCInst> &Instructions) {
1402 MCInst tmpInst;
1403 tmpInst.setOpcode(Opcode);
1404 tmpInst.addOperand(MCOperand::createReg(Reg0));
1405 tmpInst.addOperand(Op1);
1406 tmpInst.setLoc(IDLoc);
1407 Instructions.push_back(tmpInst);
1408}
1409
1410void emitRI(unsigned Opcode, unsigned Reg0, int32_t Imm, SMLoc IDLoc,
1411 SmallVectorImpl<MCInst> &Instructions) {
1412 emitRX(Opcode, Reg0, MCOperand::createImm(Imm), IDLoc, Instructions);
1413}
1414
1415void emitRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, SMLoc IDLoc,
1416 SmallVectorImpl<MCInst> &Instructions) {
1417 emitRX(Opcode, Reg0, MCOperand::createReg(Reg1), IDLoc, Instructions);
1418}
1419
1420void emitII(unsigned Opcode, int16_t Imm1, int16_t Imm2, SMLoc IDLoc,
1421 SmallVectorImpl<MCInst> &Instructions) {
1422 MCInst tmpInst;
1423 tmpInst.setOpcode(Opcode);
1424 tmpInst.addOperand(MCOperand::createImm(Imm1));
1425 tmpInst.addOperand(MCOperand::createImm(Imm2));
1426 tmpInst.setLoc(IDLoc);
1427 Instructions.push_back(tmpInst);
1428}
1429
1430void emitR(unsigned Opcode, unsigned Reg0, SMLoc IDLoc,
1431 SmallVectorImpl<MCInst> &Instructions) {
1432 MCInst tmpInst;
1433 tmpInst.setOpcode(Opcode);
1434 tmpInst.addOperand(MCOperand::createReg(Reg0));
1435 tmpInst.setLoc(IDLoc);
1436 Instructions.push_back(tmpInst);
1437}
1438
1439void emitRRX(unsigned Opcode, unsigned Reg0, unsigned Reg1, MCOperand Op2,
1440 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1441 MCInst tmpInst;
1442 tmpInst.setOpcode(Opcode);
1443 tmpInst.addOperand(MCOperand::createReg(Reg0));
1444 tmpInst.addOperand(MCOperand::createReg(Reg1));
1445 tmpInst.addOperand(Op2);
1446 tmpInst.setLoc(IDLoc);
1447 Instructions.push_back(tmpInst);
1448}
1449
1450void emitRRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, unsigned Reg2,
1451 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1452 emitRRX(Opcode, Reg0, Reg1, MCOperand::createReg(Reg2), IDLoc,
1453 Instructions);
1454}
1455
1456void emitRRI(unsigned Opcode, unsigned Reg0, unsigned Reg1, int16_t Imm,
1457 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1458 emitRRX(Opcode, Reg0, Reg1, MCOperand::createImm(Imm), IDLoc,
1459 Instructions);
1460}
1461
1462void emitAppropriateDSLL(unsigned DstReg, unsigned SrcReg, int16_t ShiftAmount,
1463 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1464 if (ShiftAmount >= 32) {
1465 emitRRI(Mips::DSLL32, DstReg, SrcReg, ShiftAmount - 32, IDLoc,
1466 Instructions);
1467 return;
1468 }
1469
1470 emitRRI(Mips::DSLL, DstReg, SrcReg, ShiftAmount, IDLoc, Instructions);
1471}
1472} // end anonymous namespace.
1473
Jack Carter9e65aa32013-03-22 00:05:30 +00001474bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001475 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001476 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001477 bool ExpandedJalSym = false;
Daniel Sandersa771fef2014-03-24 14:05:39 +00001478
Jack Carter9e65aa32013-03-22 00:05:30 +00001479 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001480
1481 if (MCID.isBranch() || MCID.isCall()) {
1482 const unsigned Opcode = Inst.getOpcode();
1483 MCOperand Offset;
1484
1485 switch (Opcode) {
1486 default:
1487 break;
Kai Nackee0245392015-01-27 19:11:28 +00001488 case Mips::BBIT0:
1489 case Mips::BBIT032:
1490 case Mips::BBIT1:
1491 case Mips::BBIT132:
1492 assert(hasCnMips() && "instruction only valid for octeon cpus");
1493 // Fall through
1494
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001495 case Mips::BEQ:
1496 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001497 case Mips::BEQ_MM:
1498 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001499 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001500 Offset = Inst.getOperand(2);
1501 if (!Offset.isImm())
1502 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001503 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001504 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001505 if (OffsetToAlignment(Offset.getImm(),
1506 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001507 return Error(IDLoc, "branch to misaligned address");
1508 break;
1509 case Mips::BGEZ:
1510 case Mips::BGTZ:
1511 case Mips::BLEZ:
1512 case Mips::BLTZ:
1513 case Mips::BGEZAL:
1514 case Mips::BLTZAL:
1515 case Mips::BC1F:
1516 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001517 case Mips::BGEZ_MM:
1518 case Mips::BGTZ_MM:
1519 case Mips::BLEZ_MM:
1520 case Mips::BLTZ_MM:
1521 case Mips::BGEZAL_MM:
1522 case Mips::BLTZAL_MM:
1523 case Mips::BC1F_MM:
1524 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001525 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001526 Offset = Inst.getOperand(1);
1527 if (!Offset.isImm())
1528 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001529 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001530 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001531 if (OffsetToAlignment(Offset.getImm(),
1532 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001533 return Error(IDLoc, "branch to misaligned address");
1534 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001535 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001536 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001537 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001538 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001539 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1540 Offset = Inst.getOperand(1);
1541 if (!Offset.isImm())
1542 break; // We'll deal with this situation later on when applying fixups.
Craig Topper55b1f292015-10-10 20:17:07 +00001543 if (!isInt<8>(Offset.getImm()))
Jozef Kolek9761e962015-01-12 12:03:34 +00001544 return Error(IDLoc, "branch target out of range");
1545 if (OffsetToAlignment(Offset.getImm(), 2LL))
1546 return Error(IDLoc, "branch to misaligned address");
1547 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001548 }
1549 }
1550
Daniel Sandersa84989a2014-06-16 13:25:35 +00001551 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1552 // We still accept it but it is a normal nop.
1553 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1554 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1555 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1556 "nop instruction");
1557 }
1558
Kai Nackee0245392015-01-27 19:11:28 +00001559 if (hasCnMips()) {
1560 const unsigned Opcode = Inst.getOpcode();
1561 MCOperand Opnd;
1562 int Imm;
1563
1564 switch (Opcode) {
1565 default:
1566 break;
1567
1568 case Mips::BBIT0:
1569 case Mips::BBIT032:
1570 case Mips::BBIT1:
1571 case Mips::BBIT132:
1572 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1573 // The offset is handled above
1574 Opnd = Inst.getOperand(1);
1575 if (!Opnd.isImm())
1576 return Error(IDLoc, "expected immediate operand kind");
1577 Imm = Opnd.getImm();
1578 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1579 Opcode == Mips::BBIT1 ? 63 : 31))
1580 return Error(IDLoc, "immediate operand value out of range");
1581 if (Imm > 31) {
1582 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1583 : Mips::BBIT132);
1584 Inst.getOperand(1).setImm(Imm - 32);
1585 }
1586 break;
1587
1588 case Mips::CINS:
1589 case Mips::CINS32:
1590 case Mips::EXTS:
1591 case Mips::EXTS32:
1592 assert(MCID.getNumOperands() == 4 && "unexpected number of operands");
1593 // Check length
1594 Opnd = Inst.getOperand(3);
1595 if (!Opnd.isImm())
1596 return Error(IDLoc, "expected immediate operand kind");
1597 Imm = Opnd.getImm();
1598 if (Imm < 0 || Imm > 31)
1599 return Error(IDLoc, "immediate operand value out of range");
1600 // Check position
1601 Opnd = Inst.getOperand(2);
1602 if (!Opnd.isImm())
1603 return Error(IDLoc, "expected immediate operand kind");
1604 Imm = Opnd.getImm();
1605 if (Imm < 0 || Imm > (Opcode == Mips::CINS ||
1606 Opcode == Mips::EXTS ? 63 : 31))
1607 return Error(IDLoc, "immediate operand value out of range");
1608 if (Imm > 31) {
1609 Inst.setOpcode(Opcode == Mips::CINS ? Mips::CINS32 : Mips::EXTS32);
1610 Inst.getOperand(2).setImm(Imm - 32);
1611 }
1612 break;
1613
1614 case Mips::SEQi:
1615 case Mips::SNEi:
1616 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1617 Opnd = Inst.getOperand(2);
1618 if (!Opnd.isImm())
1619 return Error(IDLoc, "expected immediate operand kind");
1620 Imm = Opnd.getImm();
1621 if (!isInt<10>(Imm))
1622 return Error(IDLoc, "immediate operand value out of range");
1623 break;
1624 }
1625 }
1626
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001627 // This expansion is not in a function called by tryExpandInstruction()
1628 // because the pseudo-instruction doesn't have a distinct opcode.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001629 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
1630 inPicMode()) {
1631 warnIfNoMacro(IDLoc);
1632
1633 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
1634
1635 // We can do this expansion if there's only 1 symbol in the argument
1636 // expression.
1637 if (countMCSymbolRefExpr(JalExpr) > 1)
1638 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
1639
1640 // FIXME: This is checking the expression can be handled by the later stages
1641 // of the assembler. We ought to leave it to those later stages but
1642 // we can't do that until we stop evaluateRelocExpr() rewriting the
1643 // expressions into non-equivalent forms.
1644 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
1645
1646 // FIXME: Add support for label+offset operands (currently causes an error).
1647 // FIXME: Add support for forward-declared local symbols.
1648 // FIXME: Add expansion for when the LargeGOT option is enabled.
1649 if (JalSym->isInSection() || JalSym->isTemporary()) {
1650 if (isABI_O32()) {
1651 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001652 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001653 // R_(MICRO)MIPS_GOT16 label
1654 // addiu $25, $25, 0
1655 // R_(MICRO)MIPS_LO16 label
1656 // jalr $25
1657 const MCExpr *Got16RelocExpr = evaluateRelocExpr(JalExpr, "got");
1658 const MCExpr *Lo16RelocExpr = evaluateRelocExpr(JalExpr, "lo");
1659
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001660 emitRRX(Mips::LW, Mips::T9, Mips::GP,
1661 MCOperand::createExpr(Got16RelocExpr), IDLoc, Instructions);
1662 emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
1663 MCOperand::createExpr(Lo16RelocExpr), IDLoc, Instructions);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001664 } else if (isABI_N32() || isABI_N64()) {
1665 // If it's a local symbol and the N32/N64 ABIs are being used,
1666 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001667 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001668 // R_(MICRO)MIPS_GOT_DISP label
1669 // jalr $25
1670 const MCExpr *GotDispRelocExpr = evaluateRelocExpr(JalExpr, "got_disp");
1671
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001672 emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
1673 MCOperand::createExpr(GotDispRelocExpr), IDLoc, Instructions);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001674 }
1675 } else {
1676 // If it's an external/weak symbol, we expand to:
1677 // lw/ld $25, 0($gp)
1678 // R_(MICRO)MIPS_CALL16 label
1679 // jalr $25
1680 const MCExpr *Call16RelocExpr = evaluateRelocExpr(JalExpr, "call16");
1681
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001682 emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
1683 MCOperand::createExpr(Call16RelocExpr), IDLoc, Instructions);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001684 }
1685
1686 MCInst JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001687 if (IsCpRestoreSet && inMicroMipsMode())
1688 JalrInst.setOpcode(Mips::JALRS_MM);
1689 else
1690 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001691 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
1692 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
1693
1694 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
1695 // This relocation is supposed to be an optimization hint for the linker
1696 // and is not necessary for correctness.
1697
1698 Inst = JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001699 ExpandedJalSym = true;
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001700 }
1701
Jack Carter9e65aa32013-03-22 00:05:30 +00001702 if (MCID.mayLoad() || MCID.mayStore()) {
1703 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001704 // reference or immediate we may have to expand instructions.
1705 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001706 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001707 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1708 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001709 MCOperand &Op = Inst.getOperand(i);
1710 if (Op.isImm()) {
1711 int MemOffset = Op.getImm();
1712 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001713 // Offset can't exceed 16bit value.
1714 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001715 return false;
1716 }
1717 } else if (Op.isExpr()) {
1718 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001719 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001720 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001721 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001722 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001723 // Expand symbol.
1724 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001725 return false;
1726 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001727 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001728 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001729 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001730 }
1731 }
1732 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001733 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001734 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001735
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001736 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001737 if (MCID.mayLoad()) {
1738 // Try to create 16-bit GP relative load instruction.
1739 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1740 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1741 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1742 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1743 MCOperand &Op = Inst.getOperand(i);
1744 if (Op.isImm()) {
1745 int MemOffset = Op.getImm();
1746 MCOperand &DstReg = Inst.getOperand(0);
1747 MCOperand &BaseReg = Inst.getOperand(1);
Craig Topper55b1f292015-10-10 20:17:07 +00001748 if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&
Jozef Koleke10a02e2015-01-28 17:27:26 +00001749 getContext().getRegisterInfo()->getRegClass(
1750 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00001751 (BaseReg.getReg() == Mips::GP ||
1752 BaseReg.getReg() == Mips::GP_64)) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001753
1754 emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
1755 IDLoc, Instructions);
Jozef Koleke10a02e2015-01-28 17:27:26 +00001756 return false;
1757 }
1758 }
1759 }
1760 } // for
1761 } // if load
1762
1763 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1764
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001765 MCOperand Opnd;
1766 int Imm;
1767
1768 switch (Inst.getOpcode()) {
1769 default:
1770 break;
1771 case Mips::ADDIUS5_MM:
1772 Opnd = Inst.getOperand(2);
1773 if (!Opnd.isImm())
1774 return Error(IDLoc, "expected immediate operand kind");
1775 Imm = Opnd.getImm();
1776 if (Imm < -8 || Imm > 7)
1777 return Error(IDLoc, "immediate operand value out of range");
1778 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001779 case Mips::ADDIUSP_MM:
1780 Opnd = Inst.getOperand(0);
1781 if (!Opnd.isImm())
1782 return Error(IDLoc, "expected immediate operand kind");
1783 Imm = Opnd.getImm();
1784 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1785 Imm % 4 != 0)
1786 return Error(IDLoc, "immediate operand value out of range");
1787 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001788 case Mips::SLL16_MM:
1789 case Mips::SRL16_MM:
1790 Opnd = Inst.getOperand(2);
1791 if (!Opnd.isImm())
1792 return Error(IDLoc, "expected immediate operand kind");
1793 Imm = Opnd.getImm();
1794 if (Imm < 1 || Imm > 8)
1795 return Error(IDLoc, "immediate operand value out of range");
1796 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001797 case Mips::LI16_MM:
1798 Opnd = Inst.getOperand(1);
1799 if (!Opnd.isImm())
1800 return Error(IDLoc, "expected immediate operand kind");
1801 Imm = Opnd.getImm();
1802 if (Imm < -1 || Imm > 126)
1803 return Error(IDLoc, "immediate operand value out of range");
1804 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001805 case Mips::ADDIUR2_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 == 1 || Imm == -1 ||
1811 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1812 return Error(IDLoc, "immediate operand value out of range");
1813 break;
Zoran Jovanovic42b84442014-10-23 11:13:59 +00001814 case Mips::ADDIUR1SP_MM:
1815 Opnd = Inst.getOperand(1);
1816 if (!Opnd.isImm())
1817 return Error(IDLoc, "expected immediate operand kind");
1818 Imm = Opnd.getImm();
1819 if (OffsetToAlignment(Imm, 4LL))
1820 return Error(IDLoc, "misaligned immediate operand value");
1821 if (Imm < 0 || Imm > 255)
1822 return Error(IDLoc, "immediate operand value out of range");
1823 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001824 case Mips::ANDI16_MM:
1825 Opnd = Inst.getOperand(2);
1826 if (!Opnd.isImm())
1827 return Error(IDLoc, "expected immediate operand kind");
1828 Imm = Opnd.getImm();
1829 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1830 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1831 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1832 return Error(IDLoc, "immediate operand value out of range");
1833 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001834 case Mips::LBU16_MM:
1835 Opnd = Inst.getOperand(2);
1836 if (!Opnd.isImm())
1837 return Error(IDLoc, "expected immediate operand kind");
1838 Imm = Opnd.getImm();
1839 if (Imm < -1 || Imm > 14)
1840 return Error(IDLoc, "immediate operand value out of range");
1841 break;
Zoran Jovanovic7ba636c2015-09-17 10:14:09 +00001842 case Mips::TEQ_MM:
1843 case Mips::TGE_MM:
1844 case Mips::TGEU_MM:
1845 case Mips::TLT_MM:
1846 case Mips::TLTU_MM:
1847 case Mips::TNE_MM:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001848 case Mips::SB16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001849 case Mips::SB16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001850 Opnd = Inst.getOperand(2);
1851 if (!Opnd.isImm())
1852 return Error(IDLoc, "expected immediate operand kind");
1853 Imm = Opnd.getImm();
1854 if (Imm < 0 || Imm > 15)
1855 return Error(IDLoc, "immediate operand value out of range");
1856 break;
1857 case Mips::LHU16_MM:
1858 case Mips::SH16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001859 case Mips::SH16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001860 Opnd = Inst.getOperand(2);
1861 if (!Opnd.isImm())
1862 return Error(IDLoc, "expected immediate operand kind");
1863 Imm = Opnd.getImm();
1864 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1865 return Error(IDLoc, "immediate operand value out of range");
1866 break;
1867 case Mips::LW16_MM:
1868 case Mips::SW16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001869 case Mips::SW16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001870 Opnd = Inst.getOperand(2);
1871 if (!Opnd.isImm())
1872 return Error(IDLoc, "expected immediate operand kind");
1873 Imm = Opnd.getImm();
1874 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1875 return Error(IDLoc, "immediate operand value out of range");
1876 break;
Zoran Jovanovic6e6a2c92015-09-16 09:14:35 +00001877 case Mips::PREFX_MM:
Jozef Kolekab6d1cc2014-12-23 19:55:34 +00001878 case Mips::CACHE:
1879 case Mips::PREF:
1880 Opnd = Inst.getOperand(2);
1881 if (!Opnd.isImm())
1882 return Error(IDLoc, "expected immediate operand kind");
1883 Imm = Opnd.getImm();
1884 if (!isUInt<5>(Imm))
1885 return Error(IDLoc, "immediate operand value out of range");
1886 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001887 case Mips::ADDIUPC_MM:
1888 MCOperand Opnd = Inst.getOperand(1);
1889 if (!Opnd.isImm())
1890 return Error(IDLoc, "expected immediate operand kind");
1891 int Imm = Opnd.getImm();
Craig Topper55b1f292015-10-10 20:17:07 +00001892 if ((Imm % 4 != 0) || !isInt<25>(Imm))
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001893 return Error(IDLoc, "immediate operand value out of range");
1894 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001895 }
1896 }
1897
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001898 MacroExpanderResultTy ExpandResult =
1899 tryExpandInstruction(Inst, IDLoc, Instructions);
1900 switch (ExpandResult) {
1901 case MER_NotAMacro:
Jack Carter9e65aa32013-03-22 00:05:30 +00001902 Instructions.push_back(Inst);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001903 break;
1904 case MER_Success:
1905 break;
1906 case MER_Fail:
1907 return true;
1908 }
Jack Carter9e65aa32013-03-22 00:05:30 +00001909
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001910 // If this instruction has a delay slot and .set reorder is active,
1911 // emit a NOP after it.
1912 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
1913 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1914
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001915 if ((Inst.getOpcode() == Mips::JalOneReg ||
1916 Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
1917 isPicAndNotNxxAbi()) {
1918 if (IsCpRestoreSet) {
1919 // We need a NOP between the JALR and the LW:
1920 // If .set reorder has been used, we've already emitted a NOP.
1921 // If .set noreorder has been used, we need to emit a NOP at this point.
1922 if (!AssemblerOptions.back()->isReorder())
1923 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1924
1925 // Load the $gp from the stack.
1926 SmallVector<MCInst, 3> LoadInsts;
1927 createCpRestoreMemOp(true /*IsLoad*/, CpRestoreOffset /*StackOffset*/,
1928 IDLoc, LoadInsts);
1929
1930 for (const MCInst &Inst : LoadInsts)
1931 Instructions.push_back(Inst);
1932
1933 } else
1934 Warning(IDLoc, "no .cprestore used in PIC mode");
1935 }
1936
Jack Carter9e65aa32013-03-22 00:05:30 +00001937 return false;
1938}
1939
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001940MipsAsmParser::MacroExpanderResultTy
1941MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
1942 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001943 switch (Inst.getOpcode()) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001944 default:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001945 return MER_NotAMacro;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001946 case Mips::LoadImm32:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001947 return expandLoadImm(Inst, true, IDLoc, Instructions) ? MER_Fail
1948 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001949 case Mips::LoadImm64:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001950 return expandLoadImm(Inst, false, IDLoc, Instructions) ? MER_Fail
1951 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001952 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001953 case Mips::LoadAddrImm64:
1954 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1955 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
1956 "expected immediate operand kind");
1957
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001958 return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,
1959 Inst.getOperand(1),
1960 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,
1961 Instructions)
1962 ? MER_Fail
1963 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001964 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001965 case Mips::LoadAddrReg64:
1966 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1967 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1968 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
1969 "expected immediate operand kind");
1970
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001971 return expandLoadAddress(Inst.getOperand(0).getReg(),
1972 Inst.getOperand(1).getReg(), Inst.getOperand(2),
1973 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,
1974 Instructions)
1975 ? MER_Fail
1976 : MER_Success;
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001977 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001978 case Mips::B_MMR6_Pseudo:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001979 return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions) ? MER_Fail
1980 : MER_Success;
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001981 case Mips::SWM_MM:
1982 case Mips::LWM_MM:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001983 return expandLoadStoreMultiple(Inst, IDLoc, Instructions) ? MER_Fail
1984 : MER_Success;
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001985 case Mips::JalOneReg:
1986 case Mips::JalTwoReg:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001987 return expandJalWithRegs(Inst, IDLoc, Instructions) ? MER_Fail
1988 : MER_Success;
Toma Tabacue1e460d2015-06-11 10:36:10 +00001989 case Mips::BneImm:
1990 case Mips::BeqImm:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001991 return expandBranchImm(Inst, IDLoc, Instructions) ? MER_Fail : MER_Success;
Toma Tabacu1a108322015-06-17 13:20:24 +00001992 case Mips::BLT:
1993 case Mips::BLE:
1994 case Mips::BGE:
1995 case Mips::BGT:
1996 case Mips::BLTU:
1997 case Mips::BLEU:
1998 case Mips::BGEU:
1999 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002000 case Mips::BLTL:
2001 case Mips::BLEL:
2002 case Mips::BGEL:
2003 case Mips::BGTL:
2004 case Mips::BLTUL:
2005 case Mips::BLEUL:
2006 case Mips::BGEUL:
2007 case Mips::BGTUL:
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002008 case Mips::BLTImmMacro:
2009 case Mips::BLEImmMacro:
2010 case Mips::BGEImmMacro:
2011 case Mips::BGTImmMacro:
2012 case Mips::BLTUImmMacro:
2013 case Mips::BLEUImmMacro:
2014 case Mips::BGEUImmMacro:
2015 case Mips::BGTUImmMacro:
2016 case Mips::BLTLImmMacro:
2017 case Mips::BLELImmMacro:
2018 case Mips::BGELImmMacro:
2019 case Mips::BGTLImmMacro:
2020 case Mips::BLTULImmMacro:
2021 case Mips::BLEULImmMacro:
2022 case Mips::BGEULImmMacro:
2023 case Mips::BGTULImmMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002024 return expandCondBranches(Inst, IDLoc, Instructions) ? MER_Fail
2025 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002026 case Mips::SDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002027 return expandDiv(Inst, IDLoc, Instructions, false, true) ? MER_Fail
2028 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002029 case Mips::DSDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002030 return expandDiv(Inst, IDLoc, Instructions, true, true) ? MER_Fail
2031 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002032 case Mips::UDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002033 return expandDiv(Inst, IDLoc, Instructions, false, false) ? MER_Fail
2034 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002035 case Mips::DUDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002036 return expandDiv(Inst, IDLoc, Instructions, true, false) ? MER_Fail
2037 : MER_Success;
Daniel Sanders6394ee52015-10-15 14:52:58 +00002038 case Mips::Ulh:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002039 return expandUlh(Inst, true, IDLoc, Instructions) ? MER_Fail : MER_Success;
Toma Tabacud88d79c2015-06-23 14:39:42 +00002040 case Mips::Ulhu:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002041 return expandUlh(Inst, false, IDLoc, Instructions) ? MER_Fail : MER_Success;
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00002042 case Mips::Ulw:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002043 return expandUlw(Inst, IDLoc, Instructions) ? MER_Fail : MER_Success;
2044 case Mips::NORImm:
2045 return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail
2046 : MER_Success;
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002047 case Mips::ADDi:
2048 case Mips::ADDiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002049 case Mips::SLTi:
2050 case Mips::SLTiu:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002051 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2052 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2053 int64_t ImmValue = Inst.getOperand(2).getImm();
2054 if (isInt<16>(ImmValue))
2055 return MER_NotAMacro;
2056 return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail
2057 : MER_Success;
2058 }
2059 return MER_NotAMacro;
2060 case Mips::ANDi:
2061 case Mips::ORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002062 case Mips::XORi:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002063 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2064 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2065 int64_t ImmValue = Inst.getOperand(2).getImm();
2066 if (isUInt<16>(ImmValue))
2067 return MER_NotAMacro;
2068 return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail
2069 : MER_Success;
2070 }
2071 return MER_NotAMacro;
Jack Carterd0bd6422013-04-18 00:41:53 +00002072 }
Jack Carter30a59822012-10-04 04:03:53 +00002073}
Jack Carter92995f12012-10-06 00:53:28 +00002074
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002075bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
2076 SmallVectorImpl<MCInst> &Instructions) {
2077 // Create a JALR instruction which is going to replace the pseudo-JAL.
2078 MCInst JalrInst;
2079 JalrInst.setLoc(IDLoc);
2080 const MCOperand FirstRegOp = Inst.getOperand(0);
2081 const unsigned Opcode = Inst.getOpcode();
2082
2083 if (Opcode == Mips::JalOneReg) {
2084 // jal $rs => jalr $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002085 if (IsCpRestoreSet && inMicroMipsMode()) {
2086 JalrInst.setOpcode(Mips::JALRS16_MM);
2087 JalrInst.addOperand(FirstRegOp);
2088 } else if (inMicroMipsMode()) {
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002089 JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002090 JalrInst.addOperand(FirstRegOp);
2091 } else {
2092 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002093 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002094 JalrInst.addOperand(FirstRegOp);
2095 }
2096 } else if (Opcode == Mips::JalTwoReg) {
2097 // jal $rd, $rs => jalr $rd, $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002098 if (IsCpRestoreSet && inMicroMipsMode())
2099 JalrInst.setOpcode(Mips::JALRS_MM);
2100 else
2101 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002102 JalrInst.addOperand(FirstRegOp);
2103 const MCOperand SecondRegOp = Inst.getOperand(1);
2104 JalrInst.addOperand(SecondRegOp);
2105 }
2106 Instructions.push_back(JalrInst);
2107
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002108 // If .set reorder is active and branch instruction has a delay slot,
2109 // emit a NOP after it.
2110 const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
2111 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) {
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002112 createNop(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc, Instructions);
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002113 }
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002114
2115 return false;
2116}
2117
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002118/// Can the value be represented by a unsigned N-bit value and a shift left?
Benjamin Kramer039b1042015-10-28 13:54:36 +00002119template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002120 unsigned BitNum = findFirstSet(x);
2121
2122 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2123}
2124
2125/// Load (or add) an immediate into a register.
2126///
2127/// @param ImmValue The immediate to load.
2128/// @param DstReg The register that will hold the immediate.
2129/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2130/// for a simple initialization.
2131/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2132/// @param IsAddress True if the immediate represents an address. False if it
2133/// is an integer.
2134/// @param IDLoc Location of the immediate in the source file.
2135/// @param Instructions The instructions emitted by this expansion.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002136bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002137 unsigned SrcReg, bool Is32BitImm,
2138 bool IsAddress, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00002139 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu00e98672015-05-01 12:19:27 +00002140 if (!Is32BitImm && !isGP64bit()) {
2141 Error(IDLoc, "instruction requires a 64-bit architecture");
2142 return true;
2143 }
2144
Daniel Sanders03f9c012015-07-14 12:24:22 +00002145 if (Is32BitImm) {
2146 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2147 // Sign extend up to 64-bit so that the predicates match the hardware
2148 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2149 // true.
2150 ImmValue = SignExtend64<32>(ImmValue);
2151 } else {
2152 Error(IDLoc, "instruction requires a 32-bit immediate");
2153 return true;
2154 }
2155 }
2156
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002157 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2158 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2159
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002160 bool UseSrcReg = false;
2161 if (SrcReg != Mips::NoRegister)
2162 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002163
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002164 unsigned TmpReg = DstReg;
2165 if (UseSrcReg && (DstReg == SrcReg)) {
2166 // At this point we need AT to perform the expansions and we exit if it is
2167 // not available.
2168 unsigned ATReg = getATReg(IDLoc);
2169 if (!ATReg)
2170 return true;
2171 TmpReg = ATReg;
2172 }
2173
Daniel Sanders03f9c012015-07-14 12:24:22 +00002174 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002175 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002176 SrcReg = ZeroReg;
2177
2178 // This doesn't quite follow the usual ABI expectations for N32 but matches
2179 // traditional assembler behaviour. N32 would normally use addiu for both
2180 // integers and addresses.
2181 if (IsAddress && !Is32BitImm) {
2182 emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
2183 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002184 }
2185
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002186 emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
2187 return false;
2188 }
2189
2190 if (isUInt<16>(ImmValue)) {
2191 unsigned TmpReg = DstReg;
2192 if (SrcReg == DstReg) {
2193 TmpReg = getATReg(IDLoc);
2194 if (!TmpReg)
2195 return true;
2196 }
2197
2198 emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002199 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002200 emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2201 return false;
2202 }
2203
2204 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002205 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002206
Toma Tabacu79588102015-04-29 10:19:56 +00002207 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2208 uint16_t Bits15To0 = ImmValue & 0xffff;
2209
Toma Tabacua3d056f2015-05-15 09:42:11 +00002210 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002211 // Traditional behaviour seems to special case this particular value. It's
2212 // not clear why other masks are handled differently.
2213 if (ImmValue == 0xffffffff) {
Daniel Sandersf1ae3672015-08-18 09:55:57 +00002214 emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, Instructions);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002215 emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, Instructions);
2216 if (UseSrcReg)
2217 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2218 return false;
2219 }
2220
2221 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002222 // upper 32 bits.
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002223 emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002224 emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, Instructions);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002225 if (Bits15To0)
2226 emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
2227 if (UseSrcReg)
2228 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2229 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002230 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002231
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002232 emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, Instructions);
2233 if (Bits15To0)
2234 emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002235 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002236 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2237 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002238 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002239
2240 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2241 if (Is32BitImm) {
2242 Error(IDLoc, "instruction requires a 32-bit immediate");
2243 return true;
2244 }
2245
2246 // Traditionally, these immediates are shifted as little as possible and as
2247 // such we align the most significant bit to bit 15 of our temporary.
2248 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2249 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2250 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2251 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
2252 emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, Instructions);
2253 emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, Instructions);
2254
2255 if (UseSrcReg)
2256 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2257
2258 return false;
2259 }
2260
2261 warnIfNoMacro(IDLoc);
2262
2263 // The remaining case is packed with a sequence of dsll and ori with zeros
2264 // being omitted and any neighbouring dsll's being coalesced.
2265 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2266
2267 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2268 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
2269 IDLoc, Instructions))
2270 return false;
2271
2272 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2273 // skip it and defer the shift to the next chunk.
2274 unsigned ShiftCarriedForwards = 16;
2275 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2276 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2277
2278 if (ImmChunk != 0) {
2279 emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
2280 Instructions);
2281 emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, Instructions);
2282 ShiftCarriedForwards = 0;
2283 }
2284
2285 ShiftCarriedForwards += 16;
2286 }
2287 ShiftCarriedForwards -= 16;
2288
2289 // Finish any remaining shifts left by trailing zeros.
2290 if (ShiftCarriedForwards)
2291 emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
2292 Instructions);
2293
2294 if (UseSrcReg)
2295 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2296
Matheus Almeida3813d572014-06-19 14:39:14 +00002297 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002298}
Jack Carter92995f12012-10-06 00:53:28 +00002299
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002300bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
2301 SmallVectorImpl<MCInst> &Instructions) {
2302 const MCOperand &ImmOp = Inst.getOperand(1);
2303 assert(ImmOp.isImm() && "expected immediate operand kind");
2304 const MCOperand &DstRegOp = Inst.getOperand(0);
2305 assert(DstRegOp.isReg() && "expected register operand kind");
2306
2307 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002308 Is32BitImm, false, IDLoc, Instructions))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002309 return true;
2310
2311 return false;
2312}
2313
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002314bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2315 const MCOperand &Offset,
2316 bool Is32BitAddress, SMLoc IDLoc,
2317 SmallVectorImpl<MCInst> &Instructions) {
2318 // la can't produce a usable address when addresses are 64-bit.
2319 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2320 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2321 // We currently can't do this because we depend on the equality
2322 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2323 Error(IDLoc, "la used to load 64-bit address");
2324 // Continue as if we had 'dla' instead.
2325 Is32BitAddress = false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002326 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002327
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002328 // dla requires 64-bit addresses.
2329 if (!Is32BitAddress && !ABI.ArePtrs64bit()) {
2330 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002331 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002332 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002333
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002334 if (!Offset.isImm())
2335 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
2336 Is32BitAddress, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002337
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002338 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
2339 IDLoc, Instructions);
Jack Carter543fdf82012-10-09 23:29:45 +00002340}
2341
Toma Tabacuf712ede2015-06-17 14:31:51 +00002342bool MipsAsmParser::loadAndAddSymbolAddress(
2343 const MCExpr *SymExpr, unsigned DstReg, unsigned SrcReg, bool Is32BitSym,
2344 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002345 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002346
Daniel Sandersd5a89412015-10-05 13:19:29 +00002347 const MCExpr *Symbol = cast<MCExpr>(SymExpr);
2348 const MipsMCExpr *HiExpr = MipsMCExpr::create(
2349 MCSymbolRefExpr::VK_Mips_ABS_HI, Symbol, getContext());
2350 const MipsMCExpr *LoExpr = MipsMCExpr::create(
2351 MCSymbolRefExpr::VK_Mips_ABS_LO, Symbol, getContext());
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002352
Toma Tabacufb9d1252015-06-22 12:08:39 +00002353 bool UseSrcReg = SrcReg != Mips::NoRegister;
2354
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002355 // This is the 64-bit symbol address expansion.
2356 if (ABI.ArePtrs64bit() && isGP64bit()) {
2357 // We always need AT for the 64-bit expansion.
2358 // If it is not available we exit.
2359 unsigned ATReg = getATReg(IDLoc);
2360 if (!ATReg)
2361 return true;
2362
Daniel Sandersd5a89412015-10-05 13:19:29 +00002363 const MipsMCExpr *HighestExpr = MipsMCExpr::create(
2364 MCSymbolRefExpr::VK_Mips_HIGHEST, Symbol, getContext());
2365 const MipsMCExpr *HigherExpr = MipsMCExpr::create(
2366 MCSymbolRefExpr::VK_Mips_HIGHER, Symbol, getContext());
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002367
2368 if (UseSrcReg && (DstReg == SrcReg)) {
2369 // If $rs is the same as $rd:
2370 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
2371 // daddiu $at, $at, %higher(sym)
2372 // dsll $at, $at, 16
2373 // daddiu $at, $at, %hi(sym)
2374 // dsll $at, $at, 16
2375 // daddiu $at, $at, %lo(sym)
2376 // daddu $rd, $at, $rd
2377 emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
2378 Instructions);
2379 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HigherExpr),
2380 IDLoc, Instructions);
2381 emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
2382 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
2383 Instructions);
2384 emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
2385 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
2386 Instructions);
2387 emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, Instructions);
2388
2389 return false;
2390 }
2391
2392 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2393 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
2394 // lui $at, %hi(sym)
2395 // daddiu $rd, $rd, %higher(sym)
2396 // daddiu $at, $at, %lo(sym)
2397 // dsll32 $rd, $rd, 0
2398 // daddu $rd, $rd, $at
2399 // (daddu $rd, $rd, $rs)
2400 emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
2401 Instructions);
2402 emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
2403 Instructions);
2404 emitRRX(Mips::DADDiu, DstReg, DstReg, MCOperand::createExpr(HigherExpr),
2405 IDLoc, Instructions);
2406 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
2407 Instructions);
2408 emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, Instructions);
2409 emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, Instructions);
2410 if (UseSrcReg)
2411 emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, Instructions);
2412
2413 return false;
2414 }
2415
2416 // And now, the 32-bit symbol address expansion:
2417 // If $rs is the same as $rd:
2418 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
2419 // ori $at, $at, %lo(sym)
2420 // addu $rd, $at, $rd
2421 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2422 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
2423 // ori $rd, $rd, %lo(sym)
2424 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00002425 unsigned TmpReg = DstReg;
2426 if (UseSrcReg && (DstReg == SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002427 // If $rs is the same as $rd, we need to use AT.
2428 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00002429 unsigned ATReg = getATReg(IDLoc);
2430 if (!ATReg)
2431 return true;
2432 TmpReg = ATReg;
2433 }
2434
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002435 emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, Instructions);
2436 emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr), IDLoc,
2437 Instructions);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002438
Toma Tabacufb9d1252015-06-22 12:08:39 +00002439 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002440 emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2441 else
2442 assert(DstReg == TmpReg);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002443
Toma Tabacu674825c2015-06-16 12:16:24 +00002444 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002445}
2446
NAKAMURA Takumi2bbc90c2015-01-23 01:02:07 +00002447bool MipsAsmParser::expandUncondBranchMMPseudo(
2448 MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00002449 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
2450 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002451
2452 MCOperand Offset = Inst.getOperand(0);
2453 if (Offset.isExpr()) {
2454 Inst.clear();
2455 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002456 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2457 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2458 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002459 } else {
2460 assert(Offset.isImm() && "expected immediate operand kind");
Craig Topper55b1f292015-10-10 20:17:07 +00002461 if (isInt<11>(Offset.getImm())) {
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002462 // If offset fits into 11 bits then this instruction becomes microMIPS
2463 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00002464 if (inMicroMipsMode())
2465 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002466 } else {
Craig Topper55b1f292015-10-10 20:17:07 +00002467 if (!isInt<17>(Offset.getImm()))
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002468 Error(IDLoc, "branch target out of range");
2469 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
2470 Error(IDLoc, "branch to misaligned address");
2471 Inst.clear();
2472 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002473 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2474 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2475 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002476 }
2477 }
2478 Instructions.push_back(Inst);
2479
Zoran Jovanovicada70912015-09-07 11:56:37 +00002480 // If .set reorder is active and branch instruction has a delay slot,
2481 // emit a NOP after it.
2482 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
2483 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Toma Tabacu234482a2015-03-16 12:03:39 +00002484 createNop(true, IDLoc, Instructions);
2485
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002486 return false;
2487}
2488
Toma Tabacue1e460d2015-06-11 10:36:10 +00002489bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc,
2490 SmallVectorImpl<MCInst> &Instructions) {
2491 const MCOperand &DstRegOp = Inst.getOperand(0);
2492 assert(DstRegOp.isReg() && "expected register operand kind");
2493
2494 const MCOperand &ImmOp = Inst.getOperand(1);
2495 assert(ImmOp.isImm() && "expected immediate operand kind");
2496
2497 const MCOperand &MemOffsetOp = Inst.getOperand(2);
2498 assert(MemOffsetOp.isImm() && "expected immediate operand kind");
2499
2500 unsigned OpCode = 0;
2501 switch(Inst.getOpcode()) {
2502 case Mips::BneImm:
2503 OpCode = Mips::BNE;
2504 break;
2505 case Mips::BeqImm:
2506 OpCode = Mips::BEQ;
2507 break;
2508 default:
2509 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
2510 break;
2511 }
2512
2513 int64_t ImmValue = ImmOp.getImm();
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002514 if (ImmValue == 0)
2515 emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
2516 Instructions);
2517 else {
Toma Tabacue1e460d2015-06-11 10:36:10 +00002518 warnIfNoMacro(IDLoc);
2519
2520 unsigned ATReg = getATReg(IDLoc);
2521 if (!ATReg)
2522 return true;
2523
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002524 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
2525 IDLoc, Instructions))
Toma Tabacue1e460d2015-06-11 10:36:10 +00002526 return true;
2527
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002528 emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, Instructions);
Toma Tabacue1e460d2015-06-11 10:36:10 +00002529 }
2530 return false;
2531}
2532
Jack Carter9e65aa32013-03-22 00:05:30 +00002533void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00002534 SmallVectorImpl<MCInst> &Instructions,
2535 bool isLoad, bool isImmOpnd) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002536 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00002537 const MCExpr *ExprOffset;
2538 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00002539 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002540 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2541 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002542 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002543 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2544 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002545 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00002546 if (isImmOpnd) {
2547 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
2548 ImmOffset = Inst.getOperand(2).getImm();
2549 LoOffset = ImmOffset & 0x0000ffff;
2550 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00002551 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00002552 if (LoOffset & 0x8000)
2553 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00002554 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00002555 ExprOffset = Inst.getOperand(2).getExpr();
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002556 // These are some of the types of expansions we perform here:
2557 // 1) lw $8, sym => lui $8, %hi(sym)
2558 // lw $8, %lo(sym)($8)
2559 // 2) lw $8, offset($9) => lui $8, %hi(offset)
2560 // add $8, $8, $9
2561 // lw $8, %lo(offset)($9)
2562 // 3) lw $8, offset($8) => lui $at, %hi(offset)
2563 // add $at, $at, $8
2564 // lw $8, %lo(offset)($at)
2565 // 4) sw $8, sym => lui $at, %hi(sym)
2566 // sw $8, %lo(sym)($at)
2567 // 5) sw $8, offset($8) => lui $at, %hi(offset)
2568 // add $at, $at, $8
2569 // sw $8, %lo(offset)($at)
2570 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
2571 // ldc1 $f0, %lo(sym)($at)
2572 //
2573 // For load instructions we can use the destination register as a temporary
2574 // if base and dst are different (examples 1 and 2) and if the base register
2575 // is general purpose otherwise we must use $at (example 6) and error if it's
2576 // not available. For stores we must use $at (examples 4 and 5) because we
2577 // must not clobber the source register setting up the offset.
2578 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
2579 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
2580 unsigned RegClassIDOp0 =
2581 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
2582 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
2583 (RegClassIDOp0 == Mips::GPR64RegClassID);
2584 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00002585 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002586 else {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002587 // At this point we need AT to perform the expansions and we exit if it is
2588 // not available.
Toma Tabacu89a712b2015-04-15 10:48:56 +00002589 TmpRegNum = getATReg(IDLoc);
2590 if (!TmpRegNum)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002591 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002592 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002593
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002594 emitRX(Mips::LUi, TmpRegNum,
2595 isImmOpnd ? MCOperand::createImm(HiOffset)
2596 : MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "hi")),
2597 IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00002598 // Add temp register to base.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002599 if (BaseRegNum != Mips::ZERO)
2600 emitRRR(Mips::ADDu, TmpRegNum, TmpRegNum, BaseRegNum, IDLoc, Instructions);
Alp Tokercb402912014-01-24 17:20:08 +00002601 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00002602 // of offset and new base.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002603 emitRRX(Inst.getOpcode(), RegOpNum, TmpRegNum,
2604 isImmOpnd
2605 ? MCOperand::createImm(LoOffset)
2606 : MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "lo")),
2607 IDLoc, Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +00002608}
2609
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002610bool
2611MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2612 SmallVectorImpl<MCInst> &Instructions) {
2613 unsigned OpNum = Inst.getNumOperands();
2614 unsigned Opcode = Inst.getOpcode();
2615 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2616
2617 assert (Inst.getOperand(OpNum - 1).isImm() &&
2618 Inst.getOperand(OpNum - 2).isReg() &&
2619 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2620
2621 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2622 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002623 (Inst.getOperand(OpNum - 2).getReg() == Mips::SP ||
2624 Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) &&
2625 (Inst.getOperand(OpNum - 3).getReg() == Mips::RA ||
2626 Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002627 // It can be implemented as SWM16 or LWM16 instruction.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002628 if (inMicroMipsMode() && hasMips32r6())
2629 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6;
2630 else
2631 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2632 }
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002633
2634 Inst.setOpcode(NewOpcode);
2635 Instructions.push_back(Inst);
2636 return false;
2637}
2638
Toma Tabacu1a108322015-06-17 13:20:24 +00002639bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
2640 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002641 bool EmittedNoMacroWarning = false;
Toma Tabacu1a108322015-06-17 13:20:24 +00002642 unsigned PseudoOpcode = Inst.getOpcode();
2643 unsigned SrcReg = Inst.getOperand(0).getReg();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002644 const MCOperand &TrgOp = Inst.getOperand(1);
Toma Tabacu1a108322015-06-17 13:20:24 +00002645 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
2646
2647 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002648 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00002649
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002650 unsigned TrgReg;
2651 if (TrgOp.isReg())
2652 TrgReg = TrgOp.getReg();
2653 else if (TrgOp.isImm()) {
2654 warnIfNoMacro(IDLoc);
2655 EmittedNoMacroWarning = true;
2656
2657 TrgReg = getATReg(IDLoc);
2658 if (!TrgReg)
2659 return true;
2660
2661 switch(PseudoOpcode) {
2662 default:
2663 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2664 case Mips::BLTImmMacro:
2665 PseudoOpcode = Mips::BLT;
2666 break;
2667 case Mips::BLEImmMacro:
2668 PseudoOpcode = Mips::BLE;
2669 break;
2670 case Mips::BGEImmMacro:
2671 PseudoOpcode = Mips::BGE;
2672 break;
2673 case Mips::BGTImmMacro:
2674 PseudoOpcode = Mips::BGT;
2675 break;
2676 case Mips::BLTUImmMacro:
2677 PseudoOpcode = Mips::BLTU;
2678 break;
2679 case Mips::BLEUImmMacro:
2680 PseudoOpcode = Mips::BLEU;
2681 break;
2682 case Mips::BGEUImmMacro:
2683 PseudoOpcode = Mips::BGEU;
2684 break;
2685 case Mips::BGTUImmMacro:
2686 PseudoOpcode = Mips::BGTU;
2687 break;
2688 case Mips::BLTLImmMacro:
2689 PseudoOpcode = Mips::BLTL;
2690 break;
2691 case Mips::BLELImmMacro:
2692 PseudoOpcode = Mips::BLEL;
2693 break;
2694 case Mips::BGELImmMacro:
2695 PseudoOpcode = Mips::BGEL;
2696 break;
2697 case Mips::BGTLImmMacro:
2698 PseudoOpcode = Mips::BGTL;
2699 break;
2700 case Mips::BLTULImmMacro:
2701 PseudoOpcode = Mips::BLTUL;
2702 break;
2703 case Mips::BLEULImmMacro:
2704 PseudoOpcode = Mips::BLEUL;
2705 break;
2706 case Mips::BGEULImmMacro:
2707 PseudoOpcode = Mips::BGEUL;
2708 break;
2709 case Mips::BGTULImmMacro:
2710 PseudoOpcode = Mips::BGTUL;
2711 break;
2712 }
2713
2714 if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
2715 false, IDLoc, Instructions))
2716 return true;
2717 }
2718
Toma Tabacu1a108322015-06-17 13:20:24 +00002719 switch (PseudoOpcode) {
2720 case Mips::BLT:
2721 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002722 case Mips::BLTL:
2723 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002724 AcceptsEquality = false;
2725 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002726 IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
2727 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002728 ZeroSrcOpcode = Mips::BGTZ;
2729 ZeroTrgOpcode = Mips::BLTZ;
2730 break;
2731 case Mips::BLE:
2732 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002733 case Mips::BLEL:
2734 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002735 AcceptsEquality = true;
2736 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002737 IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
2738 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002739 ZeroSrcOpcode = Mips::BGEZ;
2740 ZeroTrgOpcode = Mips::BLEZ;
2741 break;
2742 case Mips::BGE:
2743 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002744 case Mips::BGEL:
2745 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002746 AcceptsEquality = true;
2747 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002748 IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
2749 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002750 ZeroSrcOpcode = Mips::BLEZ;
2751 ZeroTrgOpcode = Mips::BGEZ;
2752 break;
2753 case Mips::BGT:
2754 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002755 case Mips::BGTL:
2756 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002757 AcceptsEquality = false;
2758 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002759 IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
2760 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002761 ZeroSrcOpcode = Mips::BLTZ;
2762 ZeroTrgOpcode = Mips::BGTZ;
2763 break;
2764 default:
2765 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2766 }
2767
Toma Tabacu1a108322015-06-17 13:20:24 +00002768 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
2769 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
2770 if (IsSrcRegZero && IsTrgRegZero) {
2771 // FIXME: All of these Opcode-specific if's are needed for compatibility
2772 // with GAS' behaviour. However, they may not generate the most efficient
2773 // code in some circumstances.
2774 if (PseudoOpcode == Mips::BLT) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002775 emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2776 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002777 return false;
2778 }
2779 if (PseudoOpcode == Mips::BLE) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002780 emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2781 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002782 Warning(IDLoc, "branch is always taken");
2783 return false;
2784 }
2785 if (PseudoOpcode == Mips::BGE) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002786 emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2787 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002788 Warning(IDLoc, "branch is always taken");
2789 return false;
2790 }
2791 if (PseudoOpcode == Mips::BGT) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002792 emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2793 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002794 return false;
2795 }
2796 if (PseudoOpcode == Mips::BGTU) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002797 emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
2798 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002799 return false;
2800 }
2801 if (AcceptsEquality) {
2802 // If both registers are $0 and the pseudo-branch accepts equality, it
2803 // will always be taken, so we emit an unconditional branch.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002804 emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
2805 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002806 Warning(IDLoc, "branch is always taken");
2807 return false;
2808 }
2809 // If both registers are $0 and the pseudo-branch does not accept
2810 // equality, it will never be taken, so we don't have to emit anything.
2811 return false;
2812 }
2813 if (IsSrcRegZero || IsTrgRegZero) {
2814 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
2815 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
2816 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
2817 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
2818 // the pseudo-branch will never be taken, so we don't emit anything.
2819 // This only applies to unsigned pseudo-branches.
2820 return false;
2821 }
2822 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
2823 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
2824 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
2825 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
2826 // the pseudo-branch will always be taken, so we emit an unconditional
2827 // branch.
2828 // This only applies to unsigned pseudo-branches.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002829 emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
2830 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002831 Warning(IDLoc, "branch is always taken");
2832 return false;
2833 }
2834 if (IsUnsigned) {
2835 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
2836 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
2837 // the pseudo-branch will be taken only when the non-zero register is
2838 // different from 0, so we emit a BNEZ.
2839 //
2840 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
2841 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
2842 // the pseudo-branch will be taken only when the non-zero register is
2843 // equal to 0, so we emit a BEQZ.
2844 //
2845 // Because only BLEU and BGEU branch on equality, we can use the
2846 // AcceptsEquality variable to decide when to emit the BEQZ.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002847 emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
2848 IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
2849 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002850 return false;
2851 }
2852 // If we have a signed pseudo-branch and one of the registers is $0,
2853 // we can use an appropriate compare-to-zero branch. We select which one
2854 // to use in the switch statement above.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002855 emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
2856 IsSrcRegZero ? TrgReg : SrcReg, MCOperand::createExpr(OffsetExpr),
2857 IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002858 return false;
2859 }
2860
2861 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
2862 // expansions. If it is not available, we return.
2863 unsigned ATRegNum = getATReg(IDLoc);
2864 if (!ATRegNum)
2865 return true;
2866
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002867 if (!EmittedNoMacroWarning)
2868 warnIfNoMacro(IDLoc);
Toma Tabacu1a108322015-06-17 13:20:24 +00002869
2870 // SLT fits well with 2 of our 4 pseudo-branches:
2871 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
2872 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
2873 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
2874 // This is accomplished by using a BNEZ with the result of the SLT.
2875 //
2876 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
2877 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
2878 // Because only BGE and BLE branch on equality, we can use the
2879 // AcceptsEquality variable to decide when to emit the BEQZ.
2880 // Note that the order of the SLT arguments doesn't change between
2881 // opposites.
2882 //
2883 // The same applies to the unsigned variants, except that SLTu is used
2884 // instead of SLT.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002885 emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
2886 ReverseOrderSLT ? TrgReg : SrcReg, ReverseOrderSLT ? SrcReg : TrgReg,
2887 IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002888
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002889 emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
2890 : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
2891 ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2892 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002893 return false;
2894}
2895
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002896bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc,
2897 SmallVectorImpl<MCInst> &Instructions,
2898 const bool IsMips64, const bool Signed) {
2899 if (hasMips32r6()) {
2900 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
2901 return false;
2902 }
2903
2904 warnIfNoMacro(IDLoc);
2905
2906 const MCOperand &RsRegOp = Inst.getOperand(0);
2907 assert(RsRegOp.isReg() && "expected register operand kind");
2908 unsigned RsReg = RsRegOp.getReg();
2909
2910 const MCOperand &RtRegOp = Inst.getOperand(1);
2911 assert(RtRegOp.isReg() && "expected register operand kind");
2912 unsigned RtReg = RtRegOp.getReg();
2913 unsigned DivOp;
2914 unsigned ZeroReg;
2915
2916 if (IsMips64) {
2917 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
2918 ZeroReg = Mips::ZERO_64;
2919 } else {
2920 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
2921 ZeroReg = Mips::ZERO;
2922 }
2923
2924 bool UseTraps = useTraps();
2925
2926 if (RsReg == Mips::ZERO || RsReg == Mips::ZERO_64) {
2927 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)
2928 Warning(IDLoc, "dividing zero by zero");
2929 if (IsMips64) {
2930 if (Signed && (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)) {
2931 if (UseTraps) {
2932 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2933 return false;
2934 }
2935
2936 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2937 return false;
2938 }
2939 } else {
2940 emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
2941 return false;
2942 }
2943 }
2944
2945 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
2946 Warning(IDLoc, "division by zero");
2947 if (Signed) {
2948 if (UseTraps) {
2949 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2950 return false;
2951 }
2952
2953 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2954 return false;
2955 }
2956 }
2957
2958 // FIXME: The values for these two BranchTarget variables may be different in
2959 // micromips. These magic numbers need to be removed.
2960 unsigned BranchTargetNoTraps;
2961 unsigned BranchTarget;
2962
2963 if (UseTraps) {
2964 BranchTarget = IsMips64 ? 12 : 8;
2965 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2966 } else {
2967 BranchTarget = IsMips64 ? 20 : 16;
2968 BranchTargetNoTraps = 8;
2969 // Branch to the li instruction.
2970 emitRRI(Mips::BNE, RtReg, ZeroReg, BranchTargetNoTraps, IDLoc,
2971 Instructions);
2972 }
2973
2974 emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
2975
2976 if (!UseTraps)
2977 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2978
2979 if (!Signed) {
2980 emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
2981 return false;
2982 }
2983
2984 unsigned ATReg = getATReg(IDLoc);
2985 if (!ATReg)
2986 return true;
2987
2988 emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, Instructions);
2989 if (IsMips64) {
2990 // Branch to the mflo instruction.
2991 emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
2992 emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, Instructions);
2993 emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, Instructions);
2994 } else {
2995 // Branch to the mflo instruction.
2996 emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
2997 emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, Instructions);
2998 }
2999
3000 if (UseTraps)
3001 emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, Instructions);
3002 else {
3003 // Branch to the mflo instruction.
3004 emitRRI(Mips::BNE, RsReg, ATReg, BranchTargetNoTraps, IDLoc, Instructions);
3005 emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, Instructions);
3006 emitII(Mips::BREAK, 0x6, 0, IDLoc, Instructions);
3007 }
3008 emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
3009 return false;
3010}
3011
Daniel Sanders6394ee52015-10-15 14:52:58 +00003012bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
3013 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacud88d79c2015-06-23 14:39:42 +00003014 if (hasMips32r6() || hasMips64r6()) {
3015 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3016 return false;
3017 }
3018
3019 warnIfNoMacro(IDLoc);
3020
3021 const MCOperand &DstRegOp = Inst.getOperand(0);
3022 assert(DstRegOp.isReg() && "expected register operand kind");
3023
3024 const MCOperand &SrcRegOp = Inst.getOperand(1);
3025 assert(SrcRegOp.isReg() && "expected register operand kind");
3026
3027 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3028 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3029
3030 unsigned DstReg = DstRegOp.getReg();
3031 unsigned SrcReg = SrcRegOp.getReg();
3032 int64_t OffsetValue = OffsetImmOp.getImm();
3033
3034 // NOTE: We always need AT for ULHU, as it is always used as the source
3035 // register for one of the LBu's.
3036 unsigned ATReg = getATReg(IDLoc);
3037 if (!ATReg)
3038 return true;
3039
3040 // When the value of offset+1 does not fit in 16 bits, we have to load the
3041 // offset in AT, (D)ADDu the original source register (if there was one), and
3042 // then use AT as the source register for the 2 generated LBu's.
3043 bool LoadedOffsetInAT = false;
3044 if (!isInt<16>(OffsetValue + 1) || !isInt<16>(OffsetValue)) {
3045 LoadedOffsetInAT = true;
3046
3047 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003048 true, IDLoc, Instructions))
Toma Tabacud88d79c2015-06-23 14:39:42 +00003049 return true;
3050
3051 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3052 // because it will make our output more similar to GAS'. For example,
3053 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3054 // instead of just an "ori $1, $9, 32768".
3055 // NOTE: If there is no source register specified in the ULHU, the parser
3056 // will interpret it as $0.
3057 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
3058 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
3059 }
3060
3061 unsigned FirstLbuDstReg = LoadedOffsetInAT ? DstReg : ATReg;
3062 unsigned SecondLbuDstReg = LoadedOffsetInAT ? ATReg : DstReg;
3063 unsigned LbuSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3064
3065 int64_t FirstLbuOffset = 0, SecondLbuOffset = 0;
3066 if (isLittle()) {
3067 FirstLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3068 SecondLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3069 } else {
3070 FirstLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3071 SecondLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3072 }
3073
3074 unsigned SllReg = LoadedOffsetInAT ? DstReg : ATReg;
3075
Daniel Sanders6394ee52015-10-15 14:52:58 +00003076 emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
3077 FirstLbuOffset, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003078
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003079 emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondLbuOffset, IDLoc,
3080 Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003081
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003082 emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003083
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003084 emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003085
3086 return false;
3087}
3088
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003089bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc,
3090 SmallVectorImpl<MCInst> &Instructions) {
3091 if (hasMips32r6() || hasMips64r6()) {
3092 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3093 return false;
3094 }
3095
3096 const MCOperand &DstRegOp = Inst.getOperand(0);
3097 assert(DstRegOp.isReg() && "expected register operand kind");
3098
3099 const MCOperand &SrcRegOp = Inst.getOperand(1);
3100 assert(SrcRegOp.isReg() && "expected register operand kind");
3101
3102 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3103 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3104
3105 unsigned SrcReg = SrcRegOp.getReg();
3106 int64_t OffsetValue = OffsetImmOp.getImm();
3107 unsigned ATReg = 0;
3108
3109 // When the value of offset+3 does not fit in 16 bits, we have to load the
3110 // offset in AT, (D)ADDu the original source register (if there was one), and
3111 // then use AT as the source register for the generated LWL and LWR.
3112 bool LoadedOffsetInAT = false;
3113 if (!isInt<16>(OffsetValue + 3) || !isInt<16>(OffsetValue)) {
3114 ATReg = getATReg(IDLoc);
3115 if (!ATReg)
3116 return true;
3117 LoadedOffsetInAT = true;
3118
3119 warnIfNoMacro(IDLoc);
3120
3121 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003122 true, IDLoc, Instructions))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003123 return true;
3124
3125 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3126 // because it will make our output more similar to GAS'. For example,
3127 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3128 // instead of just an "ori $1, $9, 32768".
3129 // NOTE: If there is no source register specified in the ULW, the parser
3130 // will interpret it as $0.
3131 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
3132 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
3133 }
3134
3135 unsigned FinalSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3136 int64_t LeftLoadOffset = 0, RightLoadOffset = 0;
3137 if (isLittle()) {
3138 LeftLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3139 RightLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3140 } else {
3141 LeftLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3142 RightLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3143 }
3144
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003145 emitRRI(Mips::LWL, DstRegOp.getReg(), FinalSrcReg, LeftLoadOffset, IDLoc,
3146 Instructions);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003147
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003148 emitRRI(Mips::LWR, DstRegOp.getReg(), FinalSrcReg, RightLoadOffset, IDLoc,
3149 Instructions);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003150
3151 return false;
3152}
3153
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003154bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
3155 SmallVectorImpl<MCInst> &Instructions) {
3156
3157 assert (Inst.getNumOperands() == 3 && "Invalid operand count");
3158 assert (Inst.getOperand(0).isReg() &&
3159 Inst.getOperand(1).isReg() &&
3160 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
3161
3162 unsigned ATReg = Mips::NoRegister;
3163 unsigned FinalDstReg = Mips::NoRegister;
3164 unsigned DstReg = Inst.getOperand(0).getReg();
3165 unsigned SrcReg = Inst.getOperand(1).getReg();
3166 int64_t ImmValue = Inst.getOperand(2).getImm();
3167
3168 bool Is32Bit = isInt<32>(ImmValue) || isUInt<32>(ImmValue);
3169
3170 unsigned FinalOpcode = Inst.getOpcode();
3171
3172 if (DstReg == SrcReg) {
3173 ATReg = getATReg(Inst.getLoc());
3174 if (!ATReg)
3175 return true;
3176 FinalDstReg = DstReg;
3177 DstReg = ATReg;
3178 }
3179
3180 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Instructions)) {
3181 switch (FinalOpcode) {
3182 default:
3183 llvm_unreachable("unimplemented expansion");
3184 case (Mips::ADDi):
3185 FinalOpcode = Mips::ADD;
3186 break;
3187 case (Mips::ADDiu):
3188 FinalOpcode = Mips::ADDu;
3189 break;
3190 case (Mips::ANDi):
3191 FinalOpcode = Mips::AND;
3192 break;
3193 case (Mips::NORImm):
3194 FinalOpcode = Mips::NOR;
3195 break;
3196 case (Mips::ORi):
3197 FinalOpcode = Mips::OR;
3198 break;
3199 case (Mips::SLTi):
3200 FinalOpcode = Mips::SLT;
3201 break;
3202 case (Mips::SLTiu):
3203 FinalOpcode = Mips::SLTu;
3204 break;
3205 case (Mips::XORi):
3206 FinalOpcode = Mips::XOR;
3207 break;
3208 }
3209
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003210 if (FinalDstReg == Mips::NoRegister)
3211 emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, Instructions);
3212 else
3213 emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc,
3214 Instructions);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003215 return false;
3216 }
3217 return true;
3218}
3219
Toma Tabacu234482a2015-03-16 12:03:39 +00003220void MipsAsmParser::createNop(bool hasShortDelaySlot, SMLoc IDLoc,
3221 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003222 if (hasShortDelaySlot)
3223 emitRR(Mips::MOVE16_MM, Mips::ZERO, Mips::ZERO, IDLoc, Instructions);
3224 else
3225 emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, Instructions);
Toma Tabacu234482a2015-03-16 12:03:39 +00003226}
3227
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003228void MipsAsmParser::createAddu(unsigned DstReg, unsigned SrcReg,
Toma Tabacu0b3e9782015-06-23 14:00:54 +00003229 unsigned TrgReg, bool Is64Bit,
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003230 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanders03f9c012015-07-14 12:24:22 +00003231 emitRRR(Is64Bit ? Mips::DADDu : Mips::ADDu, DstReg, SrcReg, TrgReg, SMLoc(),
3232 Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003233}
3234
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003235void MipsAsmParser::createCpRestoreMemOp(
3236 bool IsLoad, int StackOffset, SMLoc IDLoc,
3237 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003238 // If the offset can not fit into 16 bits, we need to expand.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003239 if (!isInt<16>(StackOffset)) {
3240 MCInst MemInst;
3241 MemInst.setOpcode(IsLoad ? Mips::LW : Mips::SW);
3242 MemInst.addOperand(MCOperand::createReg(Mips::GP));
3243 MemInst.addOperand(MCOperand::createReg(Mips::SP));
3244 MemInst.addOperand(MCOperand::createImm(StackOffset));
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003245 expandMemInst(MemInst, IDLoc, Instructions, IsLoad, true /*HasImmOpnd*/);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003246 return;
3247 }
3248
3249 emitRRI(IsLoad ? Mips::LW : Mips::SW, Mips::GP, Mips::SP, StackOffset, IDLoc,
3250 Instructions);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003251}
3252
Matheus Almeida595fcab2014-06-11 15:05:56 +00003253unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
3254 // As described by the Mips32r2 spec, the registers Rd and Rs for
3255 // jalr.hb must be different.
3256 unsigned Opcode = Inst.getOpcode();
3257
3258 if (Opcode == Mips::JALR_HB &&
3259 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
3260 return Match_RequiresDifferentSrcAndDst;
3261
3262 return Match_Success;
3263}
3264
Daniel Sanders52da7af2015-11-06 12:11:03 +00003265static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
3266 uint64_t ErrorInfo) {
3267 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
3268 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
3269 if (ErrorLoc == SMLoc())
3270 return Loc;
3271 return ErrorLoc;
3272 }
3273 return Loc;
3274}
3275
David Blaikie960ea3f2014-06-08 16:18:35 +00003276bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3277 OperandVector &Operands,
3278 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003279 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00003280 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00003281
Jack Carterb4dbc172012-09-05 23:34:03 +00003282 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00003283 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00003284 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003285 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00003286
3287 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003288 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003289 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00003290 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00003291 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00003292 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00003293 return false;
3294 }
3295 case Match_MissingFeature:
3296 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
3297 return true;
3298 case Match_InvalidOperand: {
3299 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00003300 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003301 if (ErrorInfo >= Operands.size())
3302 return Error(IDLoc, "too few operands for instruction");
3303
Daniel Sanders52da7af2015-11-06 12:11:03 +00003304 ErrorLoc = Operands[ErrorInfo]->getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00003305 if (ErrorLoc == SMLoc())
3306 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00003307 }
3308
3309 return Error(ErrorLoc, "invalid operand for instruction");
3310 }
3311 case Match_MnemonicFail:
3312 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00003313 case Match_RequiresDifferentSrcAndDst:
3314 return Error(IDLoc, "source and destination must be different");
Daniel Sanders52da7af2015-11-06 12:11:03 +00003315 case Match_Immz:
3316 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00003317 case Match_UImm1_0:
3318 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3319 "expected 1-bit unsigned immediate");
Daniel Sandersea4f6532015-11-06 12:22:31 +00003320 case Match_UImm2_0:
3321 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3322 "expected 2-bit unsigned immediate");
3323 case Match_UImm2_1:
3324 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3325 "expected immediate in range 1 .. 4");
Daniel Sanders38ce0f62015-11-06 12:31:27 +00003326 case Match_UImm3_0:
3327 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3328 "expected 3-bit unsigned immediate");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00003329 case Match_UImm4_0:
3330 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3331 "expected 4-bit unsigned immediate");
Jack Carterb4dbc172012-09-05 23:34:03 +00003332 }
Craig Topper589ceee2015-01-03 08:16:34 +00003333
3334 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00003335}
3336
Toma Tabacud9d344b2015-04-27 14:05:04 +00003337void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
3338 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
3339 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
3340 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003341}
3342
Toma Tabacu81496c12015-05-20 08:54:45 +00003343void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
3344 if (!AssemblerOptions.back()->isMacro())
3345 Warning(Loc, "macro instruction expanded into multiple instructions");
3346}
3347
Daniel Sandersef638fe2014-10-03 15:37:37 +00003348void
3349MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
3350 SMRange Range, bool ShowColors) {
3351 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00003352 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00003353 ShowColors);
3354}
3355
Jack Carter1ac53222013-02-20 23:11:17 +00003356int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003357 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003358
Vladimir Medic4c299852013-11-06 11:27:05 +00003359 CC = StringSwitch<unsigned>(Name)
3360 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003361 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00003362 .Case("a0", 4)
3363 .Case("a1", 5)
3364 .Case("a2", 6)
3365 .Case("a3", 7)
3366 .Case("v0", 2)
3367 .Case("v1", 3)
3368 .Case("s0", 16)
3369 .Case("s1", 17)
3370 .Case("s2", 18)
3371 .Case("s3", 19)
3372 .Case("s4", 20)
3373 .Case("s5", 21)
3374 .Case("s6", 22)
3375 .Case("s7", 23)
3376 .Case("k0", 26)
3377 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003378 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00003379 .Case("sp", 29)
3380 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003381 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00003382 .Case("ra", 31)
3383 .Case("t0", 8)
3384 .Case("t1", 9)
3385 .Case("t2", 10)
3386 .Case("t3", 11)
3387 .Case("t4", 12)
3388 .Case("t5", 13)
3389 .Case("t6", 14)
3390 .Case("t7", 15)
3391 .Case("t8", 24)
3392 .Case("t9", 25)
3393 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003394
Toma Tabacufda445c2014-09-15 15:33:01 +00003395 if (!(isABI_N32() || isABI_N64()))
3396 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003397
Daniel Sandersef638fe2014-10-03 15:37:37 +00003398 if (12 <= CC && CC <= 15) {
3399 // Name is one of t4-t7
3400 AsmToken RegTok = getLexer().peekTok();
3401 SMRange RegRange = RegTok.getLocRange();
3402
3403 StringRef FixedName = StringSwitch<StringRef>(Name)
3404 .Case("t4", "t0")
3405 .Case("t5", "t1")
3406 .Case("t6", "t2")
3407 .Case("t7", "t3")
3408 .Default("");
3409 assert(FixedName != "" && "Register name is not one of t4-t7.");
3410
3411 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
3412 "Did you mean $" + FixedName + "?", RegRange);
3413 }
3414
Toma Tabacufda445c2014-09-15 15:33:01 +00003415 // Although SGI documentation just cuts out t0-t3 for n32/n64,
3416 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
3417 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
3418 if (8 <= CC && CC <= 11)
3419 CC += 4;
3420
3421 if (CC == -1)
3422 CC = StringSwitch<unsigned>(Name)
3423 .Case("a4", 8)
3424 .Case("a5", 9)
3425 .Case("a6", 10)
3426 .Case("a7", 11)
3427 .Case("kt0", 26)
3428 .Case("kt1", 27)
3429 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003430
3431 return CC;
3432}
Jack Carterd0bd6422013-04-18 00:41:53 +00003433
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003434int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
3435 int CC;
3436
3437 CC = StringSwitch<unsigned>(Name)
3438 .Case("hwr_cpunum", 0)
3439 .Case("hwr_synci_step", 1)
3440 .Case("hwr_cc", 2)
3441 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00003442 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003443 .Default(-1);
3444
3445 return CC;
3446}
3447
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003448int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003449
Jack Cartera63b16a2012-09-07 00:23:42 +00003450 if (Name[0] == 'f') {
3451 StringRef NumString = Name.substr(1);
3452 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003453 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003454 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003455 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00003456 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003457 return IntVal;
3458 }
3459 return -1;
3460}
Jack Cartera63b16a2012-09-07 00:23:42 +00003461
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003462int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
3463
3464 if (Name.startswith("fcc")) {
3465 StringRef NumString = Name.substr(3);
3466 unsigned IntVal;
3467 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003468 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003469 if (IntVal > 7) // There are only 8 fcc registers.
3470 return -1;
3471 return IntVal;
3472 }
3473 return -1;
3474}
3475
3476int MipsAsmParser::matchACRegisterName(StringRef Name) {
3477
Akira Hatanaka274d24c2013-08-14 01:15:52 +00003478 if (Name.startswith("ac")) {
3479 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003480 unsigned IntVal;
3481 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003482 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003483 if (IntVal > 3) // There are only 3 acc registers.
3484 return -1;
3485 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00003486 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003487 return -1;
3488}
Jack Carterd0bd6422013-04-18 00:41:53 +00003489
Jack Carter5dc8ac92013-09-25 23:50:44 +00003490int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
3491 unsigned IntVal;
3492
3493 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
3494 return -1;
3495
3496 if (IntVal > 31)
3497 return -1;
3498
3499 return IntVal;
3500}
3501
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003502int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
3503 int CC;
3504
3505 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00003506 .Case("msair", 0)
3507 .Case("msacsr", 1)
3508 .Case("msaaccess", 2)
3509 .Case("msasave", 3)
3510 .Case("msamodify", 4)
3511 .Case("msarequest", 5)
3512 .Case("msamap", 6)
3513 .Case("msaunmap", 7)
3514 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003515
3516 return CC;
3517}
3518
Toma Tabacu89a712b2015-04-15 10:48:56 +00003519unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00003520 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00003521 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00003522 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00003523 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00003524 return 0;
3525 }
3526 unsigned AT = getReg(
3527 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00003528 return AT;
3529}
Jack Carter0b744b32012-10-04 02:29:46 +00003530
Jack Carterd0bd6422013-04-18 00:41:53 +00003531unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00003532 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00003533}
3534
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003535unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003536 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00003537 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003538}
3539
Jack Carter873c7242013-01-12 01:03:14 +00003540int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003541 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00003542 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00003543 return -1;
3544
Jack Carter873c7242013-01-12 01:03:14 +00003545 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00003546}
3547
Toma Tabacu13964452014-09-04 13:23:44 +00003548bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003549 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00003550 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003551
Jack Carter30a59822012-10-04 04:03:53 +00003552 // Check if the current operand has a custom associated parser, if so, try to
3553 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00003554 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3555 if (ResTy == MatchOperand_Success)
3556 return false;
3557 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3558 // there was a match, but an error occurred, in which case, just return that
3559 // the operand parsing failed.
3560 if (ResTy == MatchOperand_ParseFail)
3561 return true;
3562
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003563 DEBUG(dbgs() << ".. Generic Parser\n");
3564
Jack Carterb4dbc172012-09-05 23:34:03 +00003565 switch (getLexer().getKind()) {
3566 default:
3567 Error(Parser.getTok().getLoc(), "unexpected token in operand");
3568 return true;
3569 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003570 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00003571 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00003572
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003573 // Almost all registers have been parsed by custom parsers. There is only
3574 // one exception to this. $zero (and it's alias $0) will reach this point
3575 // for div, divu, and similar instructions because it is not an operand
3576 // to the instruction definition but an explicit register. Special case
3577 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00003578 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00003579 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003580
Jack Carterd0bd6422013-04-18 00:41:53 +00003581 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00003582 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003583 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00003584 return true;
3585
Jack Carter873c7242013-01-12 01:03:14 +00003586 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00003587 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00003588 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00003589 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003590 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00003591
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003592 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003593 return false;
3594 }
Vladimir Medic4c299852013-11-06 11:27:05 +00003595 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00003596 case AsmToken::LParen:
3597 case AsmToken::Minus:
3598 case AsmToken::Plus:
3599 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00003600 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00003601 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003602 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00003603 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003604 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00003605 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00003606 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003607 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003608 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003609 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00003610 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00003611 return true;
3612
Jack Carter873c7242013-01-12 01:03:14 +00003613 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3614
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003615 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00003616 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003617 } // case AsmToken::Percent
3618 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00003619 return true;
3620}
3621
Vladimir Medic4c299852013-11-06 11:27:05 +00003622const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00003623 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00003624 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00003625 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00003626 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00003627 // It's a constant, evaluate reloc value.
3628 int16_t Val;
3629 switch (getVariantKind(RelocStr)) {
3630 case MCSymbolRefExpr::VK_Mips_ABS_LO:
3631 // Get the 1st 16-bits.
3632 Val = MCE->getValue() & 0xffff;
3633 break;
3634 case MCSymbolRefExpr::VK_Mips_ABS_HI:
3635 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
3636 // 16 bits being negative.
3637 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
3638 break;
3639 case MCSymbolRefExpr::VK_Mips_HIGHER:
3640 // Get the 3rd 16-bits.
3641 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
3642 break;
3643 case MCSymbolRefExpr::VK_Mips_HIGHEST:
3644 // Get the 4th 16-bits.
3645 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
3646 break;
3647 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00003648 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00003649 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00003650 return MCConstantExpr::create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00003651 }
3652
Jack Carterb5cf5902013-04-17 00:18:04 +00003653 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003654 // It's a symbol, create a symbolic expression from the symbol.
Toma Tabacu07c97b32015-06-17 10:43:45 +00003655 const MCSymbol *Symbol = &MSRE->getSymbol();
Jack Carterb5cf5902013-04-17 00:18:04 +00003656 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003657 Res = MCSymbolRefExpr::create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003658 return Res;
3659 }
3660
3661 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00003662 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
3663
Sasa Stankovic06c47802014-04-03 10:37:45 +00003664 // Try to create target expression.
3665 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
Jim Grosbach13760bd2015-05-30 01:25:56 +00003666 return MipsMCExpr::create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00003667
Jack Carterd0bd6422013-04-18 00:41:53 +00003668 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
3669 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003670 Res = MCBinaryExpr::create(BE->getOpcode(), LExp, RExp, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003671 return Res;
3672 }
3673
3674 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003675 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003676 Res = MCUnaryExpr::create(UN->getOpcode(), UnExp, getContext());
Jack Carterd0bd6422013-04-18 00:41:53 +00003677 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00003678 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003679 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00003680 return Expr;
3681}
3682
3683bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
3684
3685 switch (Expr->getKind()) {
3686 case MCExpr::Constant:
3687 return true;
3688 case MCExpr::SymbolRef:
3689 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
3690 case MCExpr::Binary:
3691 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
3692 if (!isEvaluated(BE->getLHS()))
3693 return false;
3694 return isEvaluated(BE->getRHS());
3695 }
3696 case MCExpr::Unary:
3697 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00003698 case MCExpr::Target:
3699 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003700 }
Jack Carterb5cf5902013-04-17 00:18:04 +00003701 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00003702}
Jack Carterd0bd6422013-04-18 00:41:53 +00003703
Jack Carterb5cf5902013-04-17 00:18:04 +00003704bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003705 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00003706 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00003707 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00003708 if (Tok.isNot(AsmToken::Identifier))
3709 return true;
3710
Yaron Keren075759a2015-03-30 15:42:36 +00003711 std::string Str = Tok.getIdentifier();
Jack Carterb5cf5902013-04-17 00:18:04 +00003712
Jack Carterd0bd6422013-04-18 00:41:53 +00003713 Parser.Lex(); // Eat the identifier.
3714 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003715 const MCExpr *IdVal;
3716 SMLoc EndLoc;
3717
3718 if (getLexer().getKind() == AsmToken::LParen) {
3719 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003720 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003721 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003722 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003723 const AsmToken &nextTok = Parser.getTok();
3724 if (nextTok.isNot(AsmToken::Identifier))
3725 return true;
3726 Str += "(%";
3727 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00003728 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00003729 if (getLexer().getKind() != AsmToken::LParen)
3730 return true;
3731 } else
3732 break;
3733 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003734 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00003735 return true;
3736
3737 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00003738 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003739
3740 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00003741 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003742
Jack Carterd0bd6422013-04-18 00:41:53 +00003743 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00003744 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003745}
3746
Jack Carterb4dbc172012-09-05 23:34:03 +00003747bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
3748 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003749 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00003750 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003751 if (ResTy == MatchOperand_Success) {
3752 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00003753 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003754 StartLoc = Operand.getStartLoc();
3755 EndLoc = Operand.getEndLoc();
3756
3757 // AFAIK, we only support numeric registers and named GPR's in CFI
3758 // directives.
3759 // Don't worry about eating tokens before failing. Using an unrecognised
3760 // register is a parse error.
3761 if (Operand.isGPRAsmReg()) {
3762 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003763 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003764 }
3765
3766 return (RegNo == (unsigned)-1);
3767 }
3768
3769 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00003770 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00003771}
3772
Jack Carterb5cf5902013-04-17 00:18:04 +00003773bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003774 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00003775 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00003776 bool Result = true;
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003777 unsigned NumOfLParen = 0;
Jack Carterb5cf5902013-04-17 00:18:04 +00003778
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003779 while (getLexer().getKind() == AsmToken::LParen) {
Jack Carterb5cf5902013-04-17 00:18:04 +00003780 Parser.Lex();
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003781 ++NumOfLParen;
3782 }
Jack Carter873c7242013-01-12 01:03:14 +00003783
Jack Carterd0bd6422013-04-18 00:41:53 +00003784 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00003785 default:
3786 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00003787 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00003788 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00003789 case AsmToken::Integer:
3790 case AsmToken::Minus:
3791 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00003792 if (isParenExpr)
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003793 Result = getParser().parseParenExprOfDepth(NumOfLParen, Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00003794 else
3795 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00003796 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00003797 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003798 break;
Jack Carter873c7242013-01-12 01:03:14 +00003799 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00003800 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00003801 }
Jack Carterb5cf5902013-04-17 00:18:04 +00003802 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003803}
3804
David Blaikie960ea3f2014-06-08 16:18:35 +00003805MipsAsmParser::OperandMatchResultTy
3806MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003807 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003808 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00003809 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00003810 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00003811 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003812 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00003813 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00003814 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00003815
Jack Carterb5cf5902013-04-17 00:18:04 +00003816 if (getLexer().getKind() == AsmToken::LParen) {
3817 Parser.Lex();
3818 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003819 }
3820
Jack Carterb5cf5902013-04-17 00:18:04 +00003821 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003822 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00003823 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003824
Jack Carterd0bd6422013-04-18 00:41:53 +00003825 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003826 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003827 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003828 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00003829 SMLoc E =
3830 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003831 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00003832 return MatchOperand_Success;
3833 }
3834 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003835 SMLoc E =
3836 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00003837
Jack Carterd0bd6422013-04-18 00:41:53 +00003838 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00003839 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00003840 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00003841 S, E, *this);
3842 Operands.push_back(
3843 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00003844 return MatchOperand_Success;
3845 }
3846 Error(Parser.getTok().getLoc(), "'(' expected");
3847 return MatchOperand_ParseFail;
3848 }
3849
Jack Carterd0bd6422013-04-18 00:41:53 +00003850 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003851 }
3852
Toma Tabacu13964452014-09-04 13:23:44 +00003853 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003854 if (Res != MatchOperand_Success)
3855 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003856
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003857 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00003858 Error(Parser.getTok().getLoc(), "')' expected");
3859 return MatchOperand_ParseFail;
3860 }
3861
Jack Carter873c7242013-01-12 01:03:14 +00003862 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3863
Jack Carterd0bd6422013-04-18 00:41:53 +00003864 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003865
Craig Topper062a2ba2014-04-25 05:30:21 +00003866 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003867 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00003868
Jack Carterd0bd6422013-04-18 00:41:53 +00003869 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00003870 std::unique_ptr<MipsOperand> op(
3871 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00003872 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00003873 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003874 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00003875 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003876 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
3877 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00003878 if (IdVal->evaluateAsAbsolute(Imm))
3879 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003880 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003881 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00003882 getContext());
3883 }
3884
David Blaikie960ea3f2014-06-08 16:18:35 +00003885 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003886 return MatchOperand_Success;
3887}
3888
David Blaikie960ea3f2014-06-08 16:18:35 +00003889bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003890 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00003891 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00003892 if (Sym) {
3893 SMLoc S = Parser.getTok().getLoc();
3894 const MCExpr *Expr;
3895 if (Sym->isVariable())
3896 Expr = Sym->getVariableValue();
3897 else
3898 return false;
3899 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003900 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00003901 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00003902 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003903 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00003904 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00003905 if (ResTy == MatchOperand_Success) {
3906 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00003907 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00003908 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003909 llvm_unreachable("Should never ParseFail");
3910 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00003911 }
3912 } else if (Expr->getKind() == MCExpr::Constant) {
3913 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00003914 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00003915 Operands.push_back(
3916 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00003917 return true;
3918 }
3919 }
3920 return false;
3921}
Jack Carterd0bd6422013-04-18 00:41:53 +00003922
Jack Carter873c7242013-01-12 01:03:14 +00003923MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003924MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00003925 StringRef Identifier,
3926 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003927 int Index = matchCPURegisterName(Identifier);
3928 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003929 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003930 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3931 return MatchOperand_Success;
3932 }
3933
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003934 Index = matchHWRegsRegisterName(Identifier);
3935 if (Index != -1) {
3936 Operands.push_back(MipsOperand::createHWRegsReg(
3937 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3938 return MatchOperand_Success;
3939 }
3940
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003941 Index = matchFPURegisterName(Identifier);
3942 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003943 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003944 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3945 return MatchOperand_Success;
3946 }
3947
3948 Index = matchFCCRegisterName(Identifier);
3949 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003950 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003951 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3952 return MatchOperand_Success;
3953 }
3954
3955 Index = matchACRegisterName(Identifier);
3956 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003957 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003958 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3959 return MatchOperand_Success;
3960 }
3961
3962 Index = matchMSA128RegisterName(Identifier);
3963 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003964 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003965 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3966 return MatchOperand_Success;
3967 }
3968
3969 Index = matchMSA128CtrlRegisterName(Identifier);
3970 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003971 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003972 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3973 return MatchOperand_Success;
3974 }
3975
3976 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00003977}
3978
3979MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003980MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003981 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00003982 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003983
3984 if (Token.is(AsmToken::Identifier)) {
3985 DEBUG(dbgs() << ".. identifier\n");
3986 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00003987 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00003988 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00003989 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003990 } else if (Token.is(AsmToken::Integer)) {
3991 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00003992 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003993 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
3994 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003995 return MatchOperand_Success;
3996 }
3997
3998 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
3999
4000 return MatchOperand_NoMatch;
4001}
4002
David Blaikie960ea3f2014-06-08 16:18:35 +00004003MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004004MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004005 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004006 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004007
4008 auto Token = Parser.getTok();
4009
4010 SMLoc S = Token.getLoc();
4011
4012 if (Token.isNot(AsmToken::Dollar)) {
4013 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
4014 if (Token.is(AsmToken::Identifier)) {
4015 if (searchSymbolAlias(Operands))
4016 return MatchOperand_Success;
4017 }
4018 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
4019 return MatchOperand_NoMatch;
4020 }
4021 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004022
Toma Tabacu13964452014-09-04 13:23:44 +00004023 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00004024 if (ResTy == MatchOperand_Success) {
4025 Parser.Lex(); // $
4026 Parser.Lex(); // identifier
4027 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004028 return ResTy;
4029}
4030
4031MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004032MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004033 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004034 switch (getLexer().getKind()) {
4035 default:
4036 return MatchOperand_NoMatch;
4037 case AsmToken::LParen:
4038 case AsmToken::Minus:
4039 case AsmToken::Plus:
4040 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00004041 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004042 case AsmToken::String:
4043 break;
4044 }
4045
4046 const MCExpr *IdVal;
4047 SMLoc S = Parser.getTok().getLoc();
4048 if (getParser().parseExpression(IdVal))
4049 return MatchOperand_ParseFail;
4050
4051 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4052 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
4053 return MatchOperand_Success;
4054}
4055
David Blaikie960ea3f2014-06-08 16:18:35 +00004056MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004057MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004058 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004059 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004060
4061 SMLoc S = getLexer().getLoc();
4062
4063 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00004064 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004065 if (ResTy != MatchOperand_NoMatch)
4066 return ResTy;
4067
Daniel Sanders315386c2014-04-01 10:40:14 +00004068 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00004069 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00004070 if (ResTy != MatchOperand_NoMatch)
4071 return ResTy;
4072
Daniel Sandersffd84362014-04-01 10:41:48 +00004073 const MCExpr *Expr = nullptr;
4074 if (Parser.parseExpression(Expr)) {
4075 // We have no way of knowing if a symbol was consumed so we must ParseFail
4076 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004077 }
Daniel Sandersffd84362014-04-01 10:41:48 +00004078 Operands.push_back(
4079 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004080 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00004081}
4082
Vladimir Medic2b953d02013-10-01 09:48:56 +00004083MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00004084MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004085 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00004086 const MCExpr *IdVal;
4087 // If the first token is '$' we may have register operand.
4088 if (Parser.getTok().is(AsmToken::Dollar))
4089 return MatchOperand_NoMatch;
4090 SMLoc S = Parser.getTok().getLoc();
4091 if (getParser().parseExpression(IdVal))
4092 return MatchOperand_ParseFail;
4093 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00004094 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00004095 int64_t Val = MCE->getValue();
4096 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4097 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00004098 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00004099 return MatchOperand_Success;
4100}
4101
Matheus Almeida779c5932013-11-18 12:32:49 +00004102MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004103MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004104 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00004105 switch (getLexer().getKind()) {
4106 default:
4107 return MatchOperand_NoMatch;
4108 case AsmToken::LParen:
4109 case AsmToken::Plus:
4110 case AsmToken::Minus:
4111 case AsmToken::Integer:
4112 break;
4113 }
4114
4115 const MCExpr *Expr;
4116 SMLoc S = Parser.getTok().getLoc();
4117
4118 if (getParser().parseExpression(Expr))
4119 return MatchOperand_ParseFail;
4120
4121 int64_t Val;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004122 if (!Expr->evaluateAsAbsolute(Val)) {
Matheus Almeida779c5932013-11-18 12:32:49 +00004123 Error(S, "expected immediate value");
4124 return MatchOperand_ParseFail;
4125 }
4126
4127 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
4128 // and because the CPU always adds one to the immediate field, the allowed
4129 // range becomes 1..4. We'll only check the range here and will deal
4130 // with the addition/subtraction when actually decoding/encoding
4131 // the instruction.
4132 if (Val < 1 || Val > 4) {
4133 Error(S, "immediate not in range (1..4)");
4134 return MatchOperand_ParseFail;
4135 }
4136
Jack Carter3b2c96e2014-01-22 23:31:38 +00004137 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004138 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00004139 return MatchOperand_Success;
4140}
4141
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004142MipsAsmParser::OperandMatchResultTy
4143MipsAsmParser::parseRegisterList(OperandVector &Operands) {
4144 MCAsmParser &Parser = getParser();
4145 SmallVector<unsigned, 10> Regs;
4146 unsigned RegNo;
4147 unsigned PrevReg = Mips::NoRegister;
4148 bool RegRange = false;
4149 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4150
4151 if (Parser.getTok().isNot(AsmToken::Dollar))
4152 return MatchOperand_ParseFail;
4153
4154 SMLoc S = Parser.getTok().getLoc();
4155 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
4156 SMLoc E = getLexer().getLoc();
4157 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
4158 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
4159 if (RegRange) {
4160 // Remove last register operand because registers from register range
4161 // should be inserted first.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004162 if ((isGP64bit() && RegNo == Mips::RA_64) ||
4163 (!isGP64bit() && RegNo == Mips::RA)) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004164 Regs.push_back(RegNo);
4165 } else {
4166 unsigned TmpReg = PrevReg + 1;
4167 while (TmpReg <= RegNo) {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004168 if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) ||
4169 (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) &&
4170 isGP64bit())) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004171 Error(E, "invalid register operand");
4172 return MatchOperand_ParseFail;
4173 }
4174
4175 PrevReg = TmpReg;
4176 Regs.push_back(TmpReg++);
4177 }
4178 }
4179
4180 RegRange = false;
4181 } else {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004182 if ((PrevReg == Mips::NoRegister) &&
4183 ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) ||
4184 (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA)))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004185 Error(E, "$16 or $31 expected");
4186 return MatchOperand_ParseFail;
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004187 } else if (!(((RegNo == Mips::FP || RegNo == Mips::RA ||
4188 (RegNo >= Mips::S0 && RegNo <= Mips::S7)) &&
4189 !isGP64bit()) ||
4190 ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 ||
4191 (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) &&
4192 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004193 Error(E, "invalid register operand");
4194 return MatchOperand_ParseFail;
4195 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004196 ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) ||
4197 (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 &&
4198 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004199 Error(E, "consecutive register numbers expected");
4200 return MatchOperand_ParseFail;
4201 }
4202
4203 Regs.push_back(RegNo);
4204 }
4205
4206 if (Parser.getTok().is(AsmToken::Minus))
4207 RegRange = true;
4208
4209 if (!Parser.getTok().isNot(AsmToken::Minus) &&
4210 !Parser.getTok().isNot(AsmToken::Comma)) {
4211 Error(E, "',' or '-' expected");
4212 return MatchOperand_ParseFail;
4213 }
4214
4215 Lex(); // Consume comma or minus
4216 if (Parser.getTok().isNot(AsmToken::Dollar))
4217 break;
4218
4219 PrevReg = RegNo;
4220 }
4221
4222 SMLoc E = Parser.getTok().getLoc();
4223 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4224 parseMemOperand(Operands);
4225 return MatchOperand_Success;
4226}
4227
Zoran Jovanovic2deca342014-12-16 14:59:10 +00004228MipsAsmParser::OperandMatchResultTy
4229MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
4230 MCAsmParser &Parser = getParser();
4231
4232 SMLoc S = Parser.getTok().getLoc();
4233 if (parseAnyRegister(Operands) != MatchOperand_Success)
4234 return MatchOperand_ParseFail;
4235
4236 SMLoc E = Parser.getTok().getLoc();
4237 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
4238 unsigned Reg = Op.getGPR32Reg();
4239 Operands.pop_back();
4240 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
4241 return MatchOperand_Success;
4242}
4243
Zoran Jovanovic41688672015-02-10 16:36:20 +00004244MipsAsmParser::OperandMatchResultTy
4245MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
4246 MCAsmParser &Parser = getParser();
4247 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4248 SmallVector<unsigned, 10> Regs;
4249
4250 if (Parser.getTok().isNot(AsmToken::Dollar))
4251 return MatchOperand_ParseFail;
4252
4253 SMLoc S = Parser.getTok().getLoc();
4254
4255 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4256 return MatchOperand_ParseFail;
4257
4258 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4259 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4260 Regs.push_back(RegNo);
4261
4262 SMLoc E = Parser.getTok().getLoc();
4263 if (Parser.getTok().isNot(AsmToken::Comma)) {
4264 Error(E, "',' expected");
4265 return MatchOperand_ParseFail;
4266 }
4267
4268 // Remove comma.
4269 Parser.Lex();
4270
4271 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4272 return MatchOperand_ParseFail;
4273
4274 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4275 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4276 Regs.push_back(RegNo);
4277
4278 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4279
4280 return MatchOperand_Success;
4281}
4282
Jack Carterdc1e35d2012-09-06 20:00:02 +00004283MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
4284
Vladimir Medic4c299852013-11-06 11:27:05 +00004285 MCSymbolRefExpr::VariantKind VK =
4286 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
4287 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
4288 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
4289 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
4290 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
4291 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
4292 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
4293 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
4294 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
4295 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
4296 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
4297 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
4298 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
4299 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
4300 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
4301 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
4302 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
4303 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00004304 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
4305 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
4306 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
4307 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
4308 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
4309 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00004310 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
4311 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00004312 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00004313
Matheus Almeida2852af82014-04-22 10:15:54 +00004314 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00004315
Jack Carterdc1e35d2012-09-06 20:00:02 +00004316 return VK;
4317}
Jack Cartera63b16a2012-09-07 00:23:42 +00004318
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004319/// Sometimes (i.e. load/stores) the operand may be followed immediately by
4320/// either this.
4321/// ::= '(', register, ')'
4322/// handle it before we iterate so we don't get tripped up by the lack of
4323/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004324bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004325 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004326 if (getLexer().is(AsmToken::LParen)) {
4327 Operands.push_back(
4328 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
4329 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004330 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004331 SMLoc Loc = getLexer().getLoc();
4332 Parser.eatToEndOfStatement();
4333 return Error(Loc, "unexpected token in argument list");
4334 }
4335 if (Parser.getTok().isNot(AsmToken::RParen)) {
4336 SMLoc Loc = getLexer().getLoc();
4337 Parser.eatToEndOfStatement();
4338 return Error(Loc, "unexpected token, expected ')'");
4339 }
4340 Operands.push_back(
4341 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
4342 Parser.Lex();
4343 }
4344 return false;
4345}
4346
4347/// Sometimes (i.e. in MSA) the operand may be followed immediately by
4348/// either one of these.
4349/// ::= '[', register, ']'
4350/// ::= '[', integer, ']'
4351/// handle it before we iterate so we don't get tripped up by the lack of
4352/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004353bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00004354 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004355 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004356 if (getLexer().is(AsmToken::LBrac)) {
4357 Operands.push_back(
4358 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
4359 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004360 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004361 SMLoc Loc = getLexer().getLoc();
4362 Parser.eatToEndOfStatement();
4363 return Error(Loc, "unexpected token in argument list");
4364 }
4365 if (Parser.getTok().isNot(AsmToken::RBrac)) {
4366 SMLoc Loc = getLexer().getLoc();
4367 Parser.eatToEndOfStatement();
4368 return Error(Loc, "unexpected token, expected ']'");
4369 }
4370 Operands.push_back(
4371 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
4372 Parser.Lex();
4373 }
4374 return false;
4375}
4376
David Blaikie960ea3f2014-06-08 16:18:35 +00004377bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
4378 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004379 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004380 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004381
4382 // We have reached first instruction, module directive are now forbidden.
4383 getTargetStreamer().forbidModuleDirective();
4384
Vladimir Medic74593e62013-07-17 15:00:42 +00004385 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00004386 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00004387 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00004388 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00004389 }
Vladimir Medic64828a12013-07-16 10:07:14 +00004390 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004391 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004392
4393 // Read the remaining operands.
4394 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4395 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004396 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004397 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004398 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004399 return Error(Loc, "unexpected token in argument list");
4400 }
Toma Tabacu13964452014-09-04 13:23:44 +00004401 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004402 return true;
4403 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00004404
Jack Carterd0bd6422013-04-18 00:41:53 +00004405 while (getLexer().is(AsmToken::Comma)) {
4406 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00004407 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004408 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004409 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004410 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004411 return Error(Loc, "unexpected token in argument list");
4412 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004413 // Parse bracket and parenthesis suffixes before we iterate
4414 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00004415 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004416 return true;
4417 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00004418 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004419 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00004420 }
4421 }
Jack Carterb4dbc172012-09-05 23:34:03 +00004422 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4423 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004424 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004425 return Error(Loc, "unexpected token in argument list");
4426 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004427 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00004428 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00004429}
4430
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004431bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004432 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004433 SMLoc Loc = getLexer().getLoc();
4434 Parser.eatToEndOfStatement();
4435 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00004436}
4437
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004438bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004439 return Error(Loc, ErrorMsg);
4440}
4441
Jack Carter0b744b32012-10-04 02:29:46 +00004442bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004443 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004444 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00004445
4446 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00004447 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00004448
4449 Parser.Lex(); // Eat "noat".
4450
Jack Carterd0bd6422013-04-18 00:41:53 +00004451 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004452 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004453 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004454 return false;
4455 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004456
4457 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004458 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004459 return false;
4460}
Jack Carterd0bd6422013-04-18 00:41:53 +00004461
Jack Carter0b744b32012-10-04 02:29:46 +00004462bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00004463 // Line can be: ".set at", which sets $at to $1
4464 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00004465 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00004466 Parser.Lex(); // Eat "at".
4467
Jack Carter0b744b32012-10-04 02:29:46 +00004468 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004469 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00004470 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00004471
4472 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004473 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004474 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00004475 }
4476
4477 if (getLexer().isNot(AsmToken::Equal)) {
4478 reportParseError("unexpected token, expected equals sign");
4479 return false;
4480 }
4481 Parser.Lex(); // Eat "=".
4482
4483 if (getLexer().isNot(AsmToken::Dollar)) {
4484 if (getLexer().is(AsmToken::EndOfStatement)) {
4485 reportParseError("no register specified");
4486 return false;
4487 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00004488 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00004489 return false;
4490 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004491 }
4492 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00004493
Toma Tabacu16a74492015-02-13 10:30:57 +00004494 // Find out what "reg" is.
4495 unsigned AtRegNo;
4496 const AsmToken &Reg = Parser.getTok();
4497 if (Reg.is(AsmToken::Identifier)) {
4498 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
4499 } else if (Reg.is(AsmToken::Integer)) {
4500 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00004501 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00004502 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00004503 return false;
4504 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004505
4506 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00004507 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004508 reportParseError("invalid register");
4509 return false;
4510 }
4511 Parser.Lex(); // Eat "reg".
4512
4513 // If this is not the end of the statement, report an error.
4514 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4515 reportParseError("unexpected token, expected end of statement");
4516 return false;
4517 }
4518
4519 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
4520
4521 Parser.Lex(); // Consume the EndOfStatement.
4522 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004523}
4524
4525bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004526 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004527 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004528 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004529 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004530 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004531 return false;
4532 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004533 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00004534 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004535 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004536 return false;
4537}
4538
4539bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004540 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004541 Parser.Lex();
4542 // If this is not the end of the statement, report an error.
4543 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004544 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004545 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00004546 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004547 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00004548 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004549 Parser.Lex(); // Consume the EndOfStatement.
4550 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004551}
4552
4553bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004554 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004555 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004556 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004557 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004558 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004559 return false;
4560 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004561 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00004562 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00004563 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004564 return false;
4565}
4566
4567bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004568 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004569 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004570 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004571 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004572 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004573 return false;
4574 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004575 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00004576 reportParseError("`noreorder' must be set before `nomacro'");
4577 return false;
4578 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004579 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00004580 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00004581 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004582 return false;
4583}
Jack Carterd76b2372013-03-21 21:44:16 +00004584
Daniel Sanders44934432014-08-07 12:03:36 +00004585bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004586 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00004587 Parser.Lex();
4588
4589 // If this is not the end of the statement, report an error.
4590 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004591 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00004592
4593 setFeatureBits(Mips::FeatureMSA, "msa");
4594 getTargetStreamer().emitDirectiveSetMsa();
4595 return false;
4596}
4597
4598bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004599 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00004600 Parser.Lex();
4601
4602 // If this is not the end of the statement, report an error.
4603 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004604 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00004605
4606 clearFeatureBits(Mips::FeatureMSA, "msa");
4607 getTargetStreamer().emitDirectiveSetNoMsa();
4608 return false;
4609}
4610
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004611bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004612 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004613 Parser.Lex(); // Eat "nodsp".
4614
4615 // If this is not the end of the statement, report an error.
4616 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4617 reportParseError("unexpected token, expected end of statement");
4618 return false;
4619 }
4620
4621 clearFeatureBits(Mips::FeatureDSP, "dsp");
4622 getTargetStreamer().emitDirectiveSetNoDsp();
4623 return false;
4624}
4625
Toma Tabacucc2502d2014-11-04 17:18:07 +00004626bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004627 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00004628 Parser.Lex(); // Eat "mips16".
4629
Jack Carter39536722014-01-22 23:08:42 +00004630 // If this is not the end of the statement, report an error.
4631 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004632 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00004633 return false;
4634 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00004635
4636 setFeatureBits(Mips::FeatureMips16, "mips16");
4637 getTargetStreamer().emitDirectiveSetMips16();
4638 Parser.Lex(); // Consume the EndOfStatement.
4639 return false;
4640}
4641
4642bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004643 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00004644 Parser.Lex(); // Eat "nomips16".
4645
4646 // If this is not the end of the statement, report an error.
4647 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4648 reportParseError("unexpected token, expected end of statement");
4649 return false;
4650 }
4651
4652 clearFeatureBits(Mips::FeatureMips16, "mips16");
4653 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00004654 Parser.Lex(); // Consume the EndOfStatement.
4655 return false;
4656}
4657
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004658bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004659 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004660 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004661 // Line can be: .set fp=32
4662 // .set fp=xx
4663 // .set fp=64
4664 Parser.Lex(); // Eat fp token
4665 AsmToken Tok = Parser.getTok();
4666 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004667 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004668 return false;
4669 }
4670 Parser.Lex(); // Eat '=' token.
4671 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004672
4673 if (!parseFpABIValue(FpAbiVal, ".set"))
4674 return false;
4675
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004676 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004677 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004678 return false;
4679 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004680 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004681 Parser.Lex(); // Consume the EndOfStatement.
4682 return false;
4683}
4684
Toma Tabacu32c72aa2015-06-30 09:36:50 +00004685bool MipsAsmParser::parseSetOddSPRegDirective() {
4686 MCAsmParser &Parser = getParser();
4687
4688 Parser.Lex(); // Eat "oddspreg".
4689 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4690 reportParseError("unexpected token, expected end of statement");
4691 return false;
4692 }
4693
4694 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4695 getTargetStreamer().emitDirectiveSetOddSPReg();
4696 return false;
4697}
4698
4699bool MipsAsmParser::parseSetNoOddSPRegDirective() {
4700 MCAsmParser &Parser = getParser();
4701
4702 Parser.Lex(); // Eat "nooddspreg".
4703 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4704 reportParseError("unexpected token, expected end of statement");
4705 return false;
4706 }
4707
4708 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4709 getTargetStreamer().emitDirectiveSetNoOddSPReg();
4710 return false;
4711}
4712
Toma Tabacu9db22db2014-09-09 10:15:38 +00004713bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004714 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00004715 SMLoc Loc = getLexer().getLoc();
4716
4717 Parser.Lex();
4718 if (getLexer().isNot(AsmToken::EndOfStatement))
4719 return reportParseError("unexpected token, expected end of statement");
4720
4721 // Always keep an element on the options "stack" to prevent the user
4722 // from changing the initial options. This is how we remember them.
4723 if (AssemblerOptions.size() == 2)
4724 return reportParseError(Loc, ".set pop with no .set push");
4725
4726 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00004727 setAvailableFeatures(
4728 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
4729 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00004730
4731 getTargetStreamer().emitDirectiveSetPop();
4732 return false;
4733}
4734
4735bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004736 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00004737 Parser.Lex();
4738 if (getLexer().isNot(AsmToken::EndOfStatement))
4739 return reportParseError("unexpected token, expected end of statement");
4740
4741 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00004742 AssemblerOptions.push_back(
4743 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00004744
4745 getTargetStreamer().emitDirectiveSetPush();
4746 return false;
4747}
4748
Toma Tabacu29696502015-06-02 09:48:04 +00004749bool MipsAsmParser::parseSetSoftFloatDirective() {
4750 MCAsmParser &Parser = getParser();
4751 Parser.Lex();
4752 if (getLexer().isNot(AsmToken::EndOfStatement))
4753 return reportParseError("unexpected token, expected end of statement");
4754
4755 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
4756 getTargetStreamer().emitDirectiveSetSoftFloat();
4757 return false;
4758}
4759
4760bool MipsAsmParser::parseSetHardFloatDirective() {
4761 MCAsmParser &Parser = getParser();
4762 Parser.Lex();
4763 if (getLexer().isNot(AsmToken::EndOfStatement))
4764 return reportParseError("unexpected token, expected end of statement");
4765
4766 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
4767 getTargetStreamer().emitDirectiveSetHardFloat();
4768 return false;
4769}
4770
Jack Carterd76b2372013-03-21 21:44:16 +00004771bool MipsAsmParser::parseSetAssignment() {
4772 StringRef Name;
4773 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00004774 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00004775
4776 if (Parser.parseIdentifier(Name))
4777 reportParseError("expected identifier after .set");
4778
4779 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00004780 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00004781 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00004782
Jack Carter3b2c96e2014-01-22 23:31:38 +00004783 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00004784 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00004785
Jim Grosbach6f482002015-05-18 18:43:14 +00004786 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00004787 Sym->setVariableValue(Value);
4788
4789 return false;
4790}
Jack Carterd0bd6422013-04-18 00:41:53 +00004791
Toma Tabacu26647792014-09-09 12:52:14 +00004792bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004793 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00004794 Parser.Lex();
4795 if (getLexer().isNot(AsmToken::EndOfStatement))
4796 return reportParseError("unexpected token, expected end of statement");
4797
4798 // Reset assembler options to their initial values.
Toma Tabacu465acfd2015-06-09 13:33:26 +00004799 setAvailableFeatures(
4800 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
4801 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00004802 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
4803
4804 getTargetStreamer().emitDirectiveSetMips0();
4805 return false;
4806}
4807
Toma Tabacu85618b32014-08-19 14:22:52 +00004808bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004809 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00004810 Parser.Lex();
4811 if (getLexer().isNot(AsmToken::Equal))
4812 return reportParseError("unexpected token, expected equals sign");
4813
4814 Parser.Lex();
4815 StringRef Arch;
4816 if (Parser.parseIdentifier(Arch))
4817 return reportParseError("expected arch identifier");
4818
4819 StringRef ArchFeatureName =
4820 StringSwitch<StringRef>(Arch)
4821 .Case("mips1", "mips1")
4822 .Case("mips2", "mips2")
4823 .Case("mips3", "mips3")
4824 .Case("mips4", "mips4")
4825 .Case("mips5", "mips5")
4826 .Case("mips32", "mips32")
4827 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00004828 .Case("mips32r3", "mips32r3")
4829 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00004830 .Case("mips32r6", "mips32r6")
4831 .Case("mips64", "mips64")
4832 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00004833 .Case("mips64r3", "mips64r3")
4834 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00004835 .Case("mips64r6", "mips64r6")
4836 .Case("cnmips", "cnmips")
4837 .Case("r4000", "mips3") // This is an implementation of Mips3.
4838 .Default("");
4839
4840 if (ArchFeatureName.empty())
4841 return reportParseError("unsupported architecture");
4842
4843 selectArch(ArchFeatureName);
4844 getTargetStreamer().emitDirectiveSetArch(Arch);
4845 return false;
4846}
4847
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004848bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004849 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004850 Parser.Lex();
4851 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004852 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004853
Matheus Almeida2852af82014-04-22 10:15:54 +00004854 switch (Feature) {
4855 default:
4856 llvm_unreachable("Unimplemented feature");
4857 case Mips::FeatureDSP:
4858 setFeatureBits(Mips::FeatureDSP, "dsp");
4859 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004860 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004861 case Mips::FeatureMicroMips:
4862 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004863 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004864 case Mips::FeatureMips1:
4865 selectArch("mips1");
4866 getTargetStreamer().emitDirectiveSetMips1();
4867 break;
4868 case Mips::FeatureMips2:
4869 selectArch("mips2");
4870 getTargetStreamer().emitDirectiveSetMips2();
4871 break;
4872 case Mips::FeatureMips3:
4873 selectArch("mips3");
4874 getTargetStreamer().emitDirectiveSetMips3();
4875 break;
4876 case Mips::FeatureMips4:
4877 selectArch("mips4");
4878 getTargetStreamer().emitDirectiveSetMips4();
4879 break;
4880 case Mips::FeatureMips5:
4881 selectArch("mips5");
4882 getTargetStreamer().emitDirectiveSetMips5();
4883 break;
4884 case Mips::FeatureMips32:
4885 selectArch("mips32");
4886 getTargetStreamer().emitDirectiveSetMips32();
4887 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004888 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004889 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00004890 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004891 break;
Daniel Sanders17793142015-02-18 16:24:50 +00004892 case Mips::FeatureMips32r3:
4893 selectArch("mips32r3");
4894 getTargetStreamer().emitDirectiveSetMips32R3();
4895 break;
4896 case Mips::FeatureMips32r5:
4897 selectArch("mips32r5");
4898 getTargetStreamer().emitDirectiveSetMips32R5();
4899 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004900 case Mips::FeatureMips32r6:
4901 selectArch("mips32r6");
4902 getTargetStreamer().emitDirectiveSetMips32R6();
4903 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004904 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004905 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00004906 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00004907 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004908 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004909 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00004910 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00004911 break;
Daniel Sanders17793142015-02-18 16:24:50 +00004912 case Mips::FeatureMips64r3:
4913 selectArch("mips64r3");
4914 getTargetStreamer().emitDirectiveSetMips64R3();
4915 break;
4916 case Mips::FeatureMips64r5:
4917 selectArch("mips64r5");
4918 getTargetStreamer().emitDirectiveSetMips64R5();
4919 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004920 case Mips::FeatureMips64r6:
4921 selectArch("mips64r6");
4922 getTargetStreamer().emitDirectiveSetMips64R6();
4923 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004924 }
4925 return false;
4926}
4927
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004928bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004929 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004930 if (getLexer().isNot(AsmToken::Comma)) {
4931 SMLoc Loc = getLexer().getLoc();
4932 Parser.eatToEndOfStatement();
4933 return Error(Loc, ErrorStr);
4934 }
4935
Matheus Almeida2852af82014-04-22 10:15:54 +00004936 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004937 return true;
4938}
4939
Daniel Sanderse2982ad2015-09-17 16:08:39 +00004940// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
4941// In this class, it is only used for .cprestore.
4942// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
4943// MipsTargetELFStreamer and MipsAsmParser.
4944bool MipsAsmParser::isPicAndNotNxxAbi() {
4945 return inPicMode() && !(isABI_N32() || isABI_N64());
4946}
4947
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004948bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00004949 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00004950 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004951
Toma Tabacudde4c462014-11-06 10:02:45 +00004952 if (inMips16Mode()) {
4953 reportParseError(".cpload is not supported in Mips16 mode");
4954 return false;
4955 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004956
David Blaikie960ea3f2014-06-08 16:18:35 +00004957 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00004958 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004959 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4960 reportParseError("expected register containing function address");
4961 return false;
4962 }
4963
David Blaikie960ea3f2014-06-08 16:18:35 +00004964 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
4965 if (!RegOpnd.isGPRAsmReg()) {
4966 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004967 return false;
4968 }
4969
Toma Tabacudde4c462014-11-06 10:02:45 +00004970 // If this is not the end of the statement, report an error.
4971 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4972 reportParseError("unexpected token, expected end of statement");
4973 return false;
4974 }
4975
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004976 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004977 return false;
4978}
4979
Daniel Sanderse2982ad2015-09-17 16:08:39 +00004980bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
4981 MCAsmParser &Parser = getParser();
4982
4983 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
4984 // is used in non-PIC mode.
4985
4986 if (inMips16Mode()) {
4987 reportParseError(".cprestore is not supported in Mips16 mode");
4988 return false;
4989 }
4990
4991 // Get the stack offset value.
4992 const MCExpr *StackOffset;
4993 int64_t StackOffsetVal;
4994 if (Parser.parseExpression(StackOffset)) {
4995 reportParseError("expected stack offset value");
4996 return false;
4997 }
4998
4999 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
5000 reportParseError("stack offset is not an absolute expression");
5001 return false;
5002 }
5003
5004 if (StackOffsetVal < 0) {
5005 Warning(Loc, ".cprestore with negative stack offset has no effect");
5006 IsCpRestoreSet = false;
5007 } else {
5008 IsCpRestoreSet = true;
5009 CpRestoreOffset = StackOffsetVal;
5010 }
5011
5012 // If this is not the end of the statement, report an error.
5013 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5014 reportParseError("unexpected token, expected end of statement");
5015 return false;
5016 }
5017
5018 // Store the $gp on the stack.
5019 SmallVector<MCInst, 3> StoreInsts;
5020 createCpRestoreMemOp(false /*IsLoad*/, CpRestoreOffset /*StackOffset*/, Loc,
5021 StoreInsts);
5022
5023 getTargetStreamer().emitDirectiveCpRestore(StoreInsts, CpRestoreOffset);
5024 Parser.Lex(); // Consume the EndOfStatement.
5025 return false;
5026}
5027
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005028bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005029 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005030 unsigned FuncReg;
5031 unsigned Save;
5032 bool SaveIsReg = true;
5033
Matheus Almeida7e815762014-06-18 13:08:59 +00005034 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005035 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005036 if (ResTy == MatchOperand_NoMatch) {
5037 reportParseError("expected register containing function address");
5038 Parser.eatToEndOfStatement();
5039 return false;
5040 }
5041
5042 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5043 if (!FuncRegOpnd.isGPRAsmReg()) {
5044 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
5045 Parser.eatToEndOfStatement();
5046 return false;
5047 }
5048
5049 FuncReg = FuncRegOpnd.getGPR32Reg();
5050 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005051
Toma Tabacu65f10572014-09-16 15:00:52 +00005052 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005053 return true;
5054
Toma Tabacu13964452014-09-04 13:23:44 +00005055 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005056 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00005057 const MCExpr *OffsetExpr;
5058 int64_t OffsetVal;
5059 SMLoc ExprLoc = getLexer().getLoc();
5060
5061 if (Parser.parseExpression(OffsetExpr) ||
5062 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
5063 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00005064 Parser.eatToEndOfStatement();
5065 return false;
5066 }
Daniel Sanders5d796282015-09-21 09:26:55 +00005067
5068 Save = OffsetVal;
5069 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00005070 } else {
5071 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5072 if (!SaveOpnd.isGPRAsmReg()) {
5073 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
5074 Parser.eatToEndOfStatement();
5075 return false;
5076 }
5077 Save = SaveOpnd.getGPR32Reg();
5078 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005079
Toma Tabacu65f10572014-09-16 15:00:52 +00005080 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005081 return true;
5082
Toma Tabacu8874eac2015-02-18 13:46:53 +00005083 const MCExpr *Expr;
5084 if (Parser.parseExpression(Expr)) {
5085 reportParseError("expected expression");
5086 return false;
5087 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005088
Toma Tabacu8874eac2015-02-18 13:46:53 +00005089 if (Expr->getKind() != MCExpr::SymbolRef) {
5090 reportParseError("expected symbol");
5091 return false;
5092 }
5093 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
5094
Daniel Sandersf173dda2015-09-22 10:50:09 +00005095 CpSaveLocation = Save;
5096 CpSaveLocationIsRegister = SaveIsReg;
5097
Toma Tabacu8874eac2015-02-18 13:46:53 +00005098 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
5099 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005100 return false;
5101}
5102
Daniel Sandersf173dda2015-09-22 10:50:09 +00005103bool MipsAsmParser::parseDirectiveCPReturn() {
5104 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
5105 CpSaveLocationIsRegister);
5106 return false;
5107}
5108
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005109bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005110 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005111 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5112 const AsmToken &Tok = Parser.getTok();
5113
5114 if (Tok.getString() == "2008") {
5115 Parser.Lex();
5116 getTargetStreamer().emitDirectiveNaN2008();
5117 return false;
5118 } else if (Tok.getString() == "legacy") {
5119 Parser.Lex();
5120 getTargetStreamer().emitDirectiveNaNLegacy();
5121 return false;
5122 }
5123 }
5124 // If we don't recognize the option passed to the .nan
5125 // directive (e.g. no option or unknown option), emit an error.
5126 reportParseError("invalid option in .nan directive");
5127 return false;
5128}
5129
Jack Carter0b744b32012-10-04 02:29:46 +00005130bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005131 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005132 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00005133 const AsmToken &Tok = Parser.getTok();
5134
5135 if (Tok.getString() == "noat") {
5136 return parseSetNoAtDirective();
5137 } else if (Tok.getString() == "at") {
5138 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00005139 } else if (Tok.getString() == "arch") {
5140 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005141 } else if (Tok.getString() == "fp") {
5142 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005143 } else if (Tok.getString() == "oddspreg") {
5144 return parseSetOddSPRegDirective();
5145 } else if (Tok.getString() == "nooddspreg") {
5146 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005147 } else if (Tok.getString() == "pop") {
5148 return parseSetPopDirective();
5149 } else if (Tok.getString() == "push") {
5150 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00005151 } else if (Tok.getString() == "reorder") {
5152 return parseSetReorderDirective();
5153 } else if (Tok.getString() == "noreorder") {
5154 return parseSetNoReorderDirective();
5155 } else if (Tok.getString() == "macro") {
5156 return parseSetMacroDirective();
5157 } else if (Tok.getString() == "nomacro") {
5158 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00005159 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00005160 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005161 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00005162 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005163 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00005164 getTargetStreamer().emitDirectiveSetNoMicroMips();
5165 Parser.eatToEndOfStatement();
5166 return false;
5167 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005168 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00005169 } else if (Tok.getString() == "mips0") {
5170 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00005171 } else if (Tok.getString() == "mips1") {
5172 return parseSetFeature(Mips::FeatureMips1);
5173 } else if (Tok.getString() == "mips2") {
5174 return parseSetFeature(Mips::FeatureMips2);
5175 } else if (Tok.getString() == "mips3") {
5176 return parseSetFeature(Mips::FeatureMips3);
5177 } else if (Tok.getString() == "mips4") {
5178 return parseSetFeature(Mips::FeatureMips4);
5179 } else if (Tok.getString() == "mips5") {
5180 return parseSetFeature(Mips::FeatureMips5);
5181 } else if (Tok.getString() == "mips32") {
5182 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00005183 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005184 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005185 } else if (Tok.getString() == "mips32r3") {
5186 return parseSetFeature(Mips::FeatureMips32r3);
5187 } else if (Tok.getString() == "mips32r5") {
5188 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005189 } else if (Tok.getString() == "mips32r6") {
5190 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005191 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005192 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005193 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005194 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005195 } else if (Tok.getString() == "mips64r3") {
5196 return parseSetFeature(Mips::FeatureMips64r3);
5197 } else if (Tok.getString() == "mips64r5") {
5198 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005199 } else if (Tok.getString() == "mips64r6") {
5200 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00005201 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005202 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005203 } else if (Tok.getString() == "nodsp") {
5204 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00005205 } else if (Tok.getString() == "msa") {
5206 return parseSetMsaDirective();
5207 } else if (Tok.getString() == "nomsa") {
5208 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00005209 } else if (Tok.getString() == "softfloat") {
5210 return parseSetSoftFloatDirective();
5211 } else if (Tok.getString() == "hardfloat") {
5212 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00005213 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00005214 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00005215 parseSetAssignment();
5216 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005217 }
Jack Carter07c818d2013-01-25 01:31:34 +00005218
Jack Carter0b744b32012-10-04 02:29:46 +00005219 return true;
5220}
5221
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005222/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00005223/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005224bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005225 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005226 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5227 for (;;) {
5228 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005229 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00005230 return true;
5231
5232 getParser().getStreamer().EmitValue(Value, Size);
5233
5234 if (getLexer().is(AsmToken::EndOfStatement))
5235 break;
5236
Jack Carter07c818d2013-01-25 01:31:34 +00005237 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005238 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00005239 Parser.Lex();
5240 }
5241 }
5242
5243 Parser.Lex();
5244 return false;
5245}
5246
Vladimir Medic4c299852013-11-06 11:27:05 +00005247/// parseDirectiveGpWord
5248/// ::= .gpword local_sym
5249bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005250 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00005251 const MCExpr *Value;
5252 // EmitGPRel32Value requires an expression, so we are using base class
5253 // method to evaluate the expression.
5254 if (getParser().parseExpression(Value))
5255 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00005256 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00005257
Vladimir Medice10c1122013-11-13 13:18:04 +00005258 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005259 return Error(getLexer().getLoc(),
5260 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00005261 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00005262 return false;
5263}
5264
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005265/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00005266/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005267bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005268 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005269 const MCExpr *Value;
5270 // EmitGPRel64Value requires an expression, so we are using base class
5271 // method to evaluate the expression.
5272 if (getParser().parseExpression(Value))
5273 return true;
5274 getParser().getStreamer().EmitGPRel64Value(Value);
5275
5276 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005277 return Error(getLexer().getLoc(),
5278 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00005279 Parser.Lex(); // Eat EndOfStatement token.
5280 return false;
5281}
5282
Jack Carter0cd3c192014-01-06 23:27:31 +00005283bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005284 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00005285 // Get the option token.
5286 AsmToken Tok = Parser.getTok();
5287 // At the moment only identifiers are supported.
5288 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005289 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00005290 Parser.eatToEndOfStatement();
5291 return false;
5292 }
5293
5294 StringRef Option = Tok.getIdentifier();
5295
5296 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005297 // MipsAsmParser needs to know if the current PIC mode changes.
5298 IsPicEnabled = false;
5299
Jack Carter0cd3c192014-01-06 23:27:31 +00005300 getTargetStreamer().emitDirectiveOptionPic0();
5301 Parser.Lex();
5302 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5303 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005304 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005305 Parser.eatToEndOfStatement();
5306 }
5307 return false;
5308 }
5309
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005310 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005311 // MipsAsmParser needs to know if the current PIC mode changes.
5312 IsPicEnabled = true;
5313
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005314 getTargetStreamer().emitDirectiveOptionPic2();
5315 Parser.Lex();
5316 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5317 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005318 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005319 Parser.eatToEndOfStatement();
5320 }
5321 return false;
5322 }
5323
Jack Carter0cd3c192014-01-06 23:27:31 +00005324 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00005325 Warning(Parser.getTok().getLoc(),
5326 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00005327 Parser.eatToEndOfStatement();
5328 return false;
5329}
5330
Toma Tabacu9ca50962015-04-16 09:53:47 +00005331/// parseInsnDirective
5332/// ::= .insn
5333bool MipsAsmParser::parseInsnDirective() {
5334 // If this is not the end of the statement, report an error.
5335 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5336 reportParseError("unexpected token, expected end of statement");
5337 return false;
5338 }
5339
5340 // The actual label marking happens in
5341 // MipsELFStreamer::createPendingLabelRelocs().
5342 getTargetStreamer().emitDirectiveInsn();
5343
5344 getParser().Lex(); // Eat EndOfStatement token.
5345 return false;
5346}
5347
Daniel Sanders7e527422014-07-10 13:38:23 +00005348/// parseDirectiveModule
5349/// ::= .module oddspreg
5350/// ::= .module nooddspreg
5351/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00005352/// ::= .module softfloat
5353/// ::= .module hardfloat
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005354bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005355 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005356 MCAsmLexer &Lexer = getLexer();
5357 SMLoc L = Lexer.getLoc();
5358
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00005359 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005360 // TODO : get a better message.
5361 reportParseError(".module directive must appear before any code");
5362 return false;
5363 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005364
Toma Tabacuc405c822015-01-23 10:40:19 +00005365 StringRef Option;
5366 if (Parser.parseIdentifier(Option)) {
5367 reportParseError("expected .module option identifier");
5368 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005369 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005370
Toma Tabacuc405c822015-01-23 10:40:19 +00005371 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005372 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005373
Toma Tabacu3c499582015-06-25 10:56:57 +00005374 // Synchronize the abiflags information with the FeatureBits information we
5375 // changed above.
5376 getTargetStreamer().updateABIInfo(*this);
5377
5378 // If printing assembly, use the recently updated abiflags information.
5379 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5380 // emitted at the end).
5381 getTargetStreamer().emitDirectiveModuleOddSPReg();
5382
Toma Tabacuc405c822015-01-23 10:40:19 +00005383 // If this is not the end of the statement, report an error.
5384 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5385 reportParseError("unexpected token, expected end of statement");
5386 return false;
5387 }
5388
5389 return false; // parseDirectiveModule has finished successfully.
5390 } else if (Option == "nooddspreg") {
5391 if (!isABI_O32()) {
5392 Error(L, "'.module nooddspreg' requires the O32 ABI");
5393 return false;
5394 }
5395
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005396 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005397
Toma Tabacu3c499582015-06-25 10:56:57 +00005398 // Synchronize the abiflags information with the FeatureBits information we
5399 // changed above.
5400 getTargetStreamer().updateABIInfo(*this);
5401
5402 // If printing assembly, use the recently updated abiflags information.
5403 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5404 // emitted at the end).
5405 getTargetStreamer().emitDirectiveModuleOddSPReg();
5406
Toma Tabacuc405c822015-01-23 10:40:19 +00005407 // If this is not the end of the statement, report an error.
5408 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5409 reportParseError("unexpected token, expected end of statement");
5410 return false;
5411 }
5412
5413 return false; // parseDirectiveModule has finished successfully.
5414 } else if (Option == "fp") {
5415 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00005416 } else if (Option == "softfloat") {
5417 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5418
5419 // Synchronize the ABI Flags information with the FeatureBits information we
5420 // updated above.
5421 getTargetStreamer().updateABIInfo(*this);
5422
5423 // If printing assembly, use the recently updated ABI Flags information.
5424 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5425 // emitted later).
5426 getTargetStreamer().emitDirectiveModuleSoftFloat();
5427
5428 // If this is not the end of the statement, report an error.
5429 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5430 reportParseError("unexpected token, expected end of statement");
5431 return false;
5432 }
5433
5434 return false; // parseDirectiveModule has finished successfully.
5435 } else if (Option == "hardfloat") {
5436 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5437
5438 // Synchronize the ABI Flags information with the FeatureBits information we
5439 // updated above.
5440 getTargetStreamer().updateABIInfo(*this);
5441
5442 // If printing assembly, use the recently updated ABI Flags information.
5443 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5444 // emitted later).
5445 getTargetStreamer().emitDirectiveModuleHardFloat();
5446
5447 // If this is not the end of the statement, report an error.
5448 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5449 reportParseError("unexpected token, expected end of statement");
5450 return false;
5451 }
5452
5453 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00005454 } else {
5455 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
5456 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005457}
5458
5459/// parseDirectiveModuleFP
5460/// ::= =32
5461/// ::= =xx
5462/// ::= =64
5463bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005464 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005465 MCAsmLexer &Lexer = getLexer();
5466
5467 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005468 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005469 return false;
5470 }
5471 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005472
Daniel Sanders7e527422014-07-10 13:38:23 +00005473 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005474 if (!parseFpABIValue(FpABI, ".module"))
5475 return false;
5476
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005477 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005478 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005479 return false;
5480 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005481
Toma Tabacua64e5402015-06-25 12:44:38 +00005482 // Synchronize the abiflags information with the FeatureBits information we
5483 // changed above.
5484 getTargetStreamer().updateABIInfo(*this);
5485
5486 // If printing assembly, use the recently updated abiflags information.
5487 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5488 // emitted at the end).
5489 getTargetStreamer().emitDirectiveModuleFP();
5490
Daniel Sanders7e527422014-07-10 13:38:23 +00005491 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005492 return false;
5493}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005494
Daniel Sanders7e527422014-07-10 13:38:23 +00005495bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005496 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005497 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005498 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005499 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005500
5501 if (Lexer.is(AsmToken::Identifier)) {
5502 StringRef Value = Parser.getTok().getString();
5503 Parser.Lex();
5504
5505 if (Value != "xx") {
5506 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5507 return false;
5508 }
5509
5510 if (!isABI_O32()) {
5511 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
5512 return false;
5513 }
5514
Daniel Sanders7e527422014-07-10 13:38:23 +00005515 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005516 if (ModuleLevelOptions) {
5517 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5518 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5519 } else {
5520 setFeatureBits(Mips::FeatureFPXX, "fpxx");
5521 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5522 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005523 return true;
5524 }
5525
5526 if (Lexer.is(AsmToken::Integer)) {
5527 unsigned Value = Parser.getTok().getIntVal();
5528 Parser.Lex();
5529
5530 if (Value != 32 && Value != 64) {
5531 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5532 return false;
5533 }
5534
5535 if (Value == 32) {
5536 if (!isABI_O32()) {
5537 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
5538 return false;
5539 }
5540
Daniel Sanders7e527422014-07-10 13:38:23 +00005541 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005542 if (ModuleLevelOptions) {
5543 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5544 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5545 } else {
5546 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
5547 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5548 }
Toma Tabacua64e5402015-06-25 12:44:38 +00005549 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00005550 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005551 if (ModuleLevelOptions) {
5552 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5553 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5554 } else {
5555 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
5556 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
5557 }
Toma Tabacua64e5402015-06-25 12:44:38 +00005558 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005559
Daniel Sanders7e527422014-07-10 13:38:23 +00005560 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005561 }
5562
5563 return false;
5564}
5565
Jack Carter0b744b32012-10-04 02:29:46 +00005566bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005567 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005568 StringRef IDVal = DirectiveID.getString();
5569
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005570 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005571 return parseDirectiveCpLoad(DirectiveID.getLoc());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005572 if (IDVal == ".cprestore")
5573 return parseDirectiveCpRestore(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00005574 if (IDVal == ".dword") {
5575 parseDataDirective(8, DirectiveID.getLoc());
5576 return false;
5577 }
Jack Carterd0bd6422013-04-18 00:41:53 +00005578 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005579 StringRef SymbolName;
5580
5581 if (Parser.parseIdentifier(SymbolName)) {
5582 reportParseError("expected identifier after .ent");
5583 return false;
5584 }
5585
5586 // There's an undocumented extension that allows an integer to
5587 // follow the name of the procedure which AFAICS is ignored by GAS.
5588 // Example: .ent foo,2
5589 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5590 if (getLexer().isNot(AsmToken::Comma)) {
5591 // Even though we accept this undocumented extension for compatibility
5592 // reasons, the additional integer argument does not actually change
5593 // the behaviour of the '.ent' directive, so we would like to discourage
5594 // its use. We do this by not referring to the extended version in
5595 // error messages which are not directly related to its use.
5596 reportParseError("unexpected token, expected end of statement");
5597 return false;
5598 }
5599 Parser.Lex(); // Eat the comma.
5600 const MCExpr *DummyNumber;
5601 int64_t DummyNumberVal;
5602 // If the user was explicitly trying to use the extended version,
5603 // we still give helpful extension-related error messages.
5604 if (Parser.parseExpression(DummyNumber)) {
5605 reportParseError("expected number after comma");
5606 return false;
5607 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00005608 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005609 reportParseError("expected an absolute expression after comma");
5610 return false;
5611 }
5612 }
5613
5614 // If this is not the end of the statement, report an error.
5615 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5616 reportParseError("unexpected token, expected end of statement");
5617 return false;
5618 }
5619
Jim Grosbach6f482002015-05-18 18:43:14 +00005620 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005621
5622 getTargetStreamer().emitDirectiveEnt(*Sym);
5623 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005624 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00005625 return false;
5626 }
5627
Jack Carter07c818d2013-01-25 01:31:34 +00005628 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005629 StringRef SymbolName;
5630
5631 if (Parser.parseIdentifier(SymbolName)) {
5632 reportParseError("expected identifier after .end");
5633 return false;
5634 }
5635
5636 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5637 reportParseError("unexpected token, expected end of statement");
5638 return false;
5639 }
5640
5641 if (CurrentFn == nullptr) {
5642 reportParseError(".end used without .ent");
5643 return false;
5644 }
5645
5646 if ((SymbolName != CurrentFn->getName())) {
5647 reportParseError(".end symbol does not match .ent symbol");
5648 return false;
5649 }
5650
5651 getTargetStreamer().emitDirectiveEnd(SymbolName);
5652 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005653 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00005654 return false;
5655 }
5656
Jack Carter07c818d2013-01-25 01:31:34 +00005657 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005658 // .frame $stack_reg, frame_size_in_bytes, $return_reg
5659 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005660 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005661 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5662 reportParseError("expected stack register");
5663 return false;
5664 }
5665
5666 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5667 if (!StackRegOpnd.isGPRAsmReg()) {
5668 reportParseError(StackRegOpnd.getStartLoc(),
5669 "expected general purpose register");
5670 return false;
5671 }
5672 unsigned StackReg = StackRegOpnd.getGPR32Reg();
5673
5674 if (Parser.getTok().is(AsmToken::Comma))
5675 Parser.Lex();
5676 else {
5677 reportParseError("unexpected token, expected comma");
5678 return false;
5679 }
5680
5681 // Parse the frame size.
5682 const MCExpr *FrameSize;
5683 int64_t FrameSizeVal;
5684
5685 if (Parser.parseExpression(FrameSize)) {
5686 reportParseError("expected frame size value");
5687 return false;
5688 }
5689
Jim Grosbach13760bd2015-05-30 01:25:56 +00005690 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005691 reportParseError("frame size not an absolute expression");
5692 return false;
5693 }
5694
5695 if (Parser.getTok().is(AsmToken::Comma))
5696 Parser.Lex();
5697 else {
5698 reportParseError("unexpected token, expected comma");
5699 return false;
5700 }
5701
5702 // Parse the return register.
5703 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00005704 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005705 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5706 reportParseError("expected return register");
5707 return false;
5708 }
5709
5710 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5711 if (!ReturnRegOpnd.isGPRAsmReg()) {
5712 reportParseError(ReturnRegOpnd.getStartLoc(),
5713 "expected general purpose register");
5714 return false;
5715 }
5716
5717 // If this is not the end of the statement, report an error.
5718 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5719 reportParseError("unexpected token, expected end of statement");
5720 return false;
5721 }
5722
5723 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
5724 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005725 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00005726 return false;
5727 }
5728
Jack Carter07c818d2013-01-25 01:31:34 +00005729 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00005730 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00005731 }
5732
Daniel Sandersd97a6342014-08-13 10:07:34 +00005733 if (IDVal == ".mask" || IDVal == ".fmask") {
5734 // .mask bitmask, frame_offset
5735 // bitmask: One bit for each register used.
5736 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
5737 // first register is expected to be saved.
5738 // Examples:
5739 // .mask 0x80000000, -4
5740 // .fmask 0x80000000, -4
5741 //
Jack Carterbe332172012-09-07 00:48:02 +00005742
Daniel Sandersd97a6342014-08-13 10:07:34 +00005743 // Parse the bitmask
5744 const MCExpr *BitMask;
5745 int64_t BitMaskVal;
5746
5747 if (Parser.parseExpression(BitMask)) {
5748 reportParseError("expected bitmask value");
5749 return false;
5750 }
5751
Jim Grosbach13760bd2015-05-30 01:25:56 +00005752 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005753 reportParseError("bitmask not an absolute expression");
5754 return false;
5755 }
5756
5757 if (Parser.getTok().is(AsmToken::Comma))
5758 Parser.Lex();
5759 else {
5760 reportParseError("unexpected token, expected comma");
5761 return false;
5762 }
5763
5764 // Parse the frame_offset
5765 const MCExpr *FrameOffset;
5766 int64_t FrameOffsetVal;
5767
5768 if (Parser.parseExpression(FrameOffset)) {
5769 reportParseError("expected frame offset value");
5770 return false;
5771 }
5772
Jim Grosbach13760bd2015-05-30 01:25:56 +00005773 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005774 reportParseError("frame offset not an absolute expression");
5775 return false;
5776 }
5777
5778 // If this is not the end of the statement, report an error.
5779 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5780 reportParseError("unexpected token, expected end of statement");
5781 return false;
5782 }
5783
5784 if (IDVal == ".mask")
5785 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
5786 else
5787 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00005788 return false;
5789 }
5790
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005791 if (IDVal == ".nan")
5792 return parseDirectiveNaN();
5793
Jack Carter07c818d2013-01-25 01:31:34 +00005794 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00005795 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00005796 return false;
5797 }
5798
Rafael Espindolab59fb732014-03-28 18:50:26 +00005799 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005800 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005801 return false;
5802 }
5803
Jack Carter07c818d2013-01-25 01:31:34 +00005804 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005805 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00005806 return false;
5807 }
5808
Jack Carter0cd3c192014-01-06 23:27:31 +00005809 if (IDVal == ".option")
5810 return parseDirectiveOption();
5811
5812 if (IDVal == ".abicalls") {
5813 getTargetStreamer().emitDirectiveAbiCalls();
5814 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005815 Error(Parser.getTok().getLoc(),
5816 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005817 // Clear line
5818 Parser.eatToEndOfStatement();
5819 }
5820 return false;
5821 }
5822
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005823 if (IDVal == ".cpsetup")
5824 return parseDirectiveCPSetup();
5825
Daniel Sandersf173dda2015-09-22 10:50:09 +00005826 if (IDVal == ".cpreturn")
5827 return parseDirectiveCPReturn();
5828
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005829 if (IDVal == ".module")
5830 return parseDirectiveModule();
5831
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00005832 if (IDVal == ".llvm_internal_mips_reallow_module_directive")
5833 return parseInternalDirectiveReallowModule();
5834
Toma Tabacu9ca50962015-04-16 09:53:47 +00005835 if (IDVal == ".insn")
5836 return parseInsnDirective();
5837
Rafael Espindola870c4e92012-01-11 03:56:41 +00005838 return true;
5839}
5840
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00005841bool MipsAsmParser::parseInternalDirectiveReallowModule() {
5842 // If this is not the end of the statement, report an error.
5843 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5844 reportParseError("unexpected token, expected end of statement");
5845 return false;
5846 }
5847
5848 getTargetStreamer().reallowModuleDirective();
5849
5850 getParser().Lex(); // Eat EndOfStatement token.
5851 return false;
5852}
5853
Rafael Espindola870c4e92012-01-11 03:56:41 +00005854extern "C" void LLVMInitializeMipsAsmParser() {
5855 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
5856 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
5857 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
5858 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
5859}
Jack Carterb4dbc172012-09-05 23:34:03 +00005860
5861#define GET_REGISTER_MATCHER
5862#define GET_MATCHER_IMPLEMENTATION
5863#include "MipsGenAsmMatcher.inc"