blob: aea022a336f45122122e87af32f9e00d9d11e402 [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();
1010 if (Size < 2 || Size > 5 || *RegList.List->begin() != Mips::S0 ||
1011 RegList.List->back() != Mips::RA)
1012 return false;
1013
1014 int PrevReg = *RegList.List->begin();
1015 for (int i = 1; i < Size - 1; i++) {
1016 int Reg = (*(RegList.List))[i];
1017 if ( Reg != PrevReg + 1)
1018 return false;
1019 PrevReg = Reg;
1020 }
1021
1022 return true;
1023 }
Vladimir Medic2b953d02013-10-01 09:48:56 +00001024 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001025 bool isLSAImm() const {
1026 if (!isConstantImm())
1027 return false;
1028 int64_t Val = getConstantImm();
1029 return 1 <= Val && Val <= 4;
1030 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001031 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001032 bool isMovePRegPair() const {
1033 if (Kind != k_RegList || RegList.List->size() != 2)
1034 return false;
1035
1036 unsigned R0 = RegList.List->front();
1037 unsigned R1 = RegList.List->back();
1038
1039 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
1040 (R0 == Mips::A1 && R1 == Mips::A3) ||
1041 (R0 == Mips::A2 && R1 == Mips::A3) ||
1042 (R0 == Mips::A0 && R1 == Mips::S5) ||
1043 (R0 == Mips::A0 && R1 == Mips::S6) ||
1044 (R0 == Mips::A0 && R1 == Mips::A1) ||
1045 (R0 == Mips::A0 && R1 == Mips::A2) ||
1046 (R0 == Mips::A0 && R1 == Mips::A3))
1047 return true;
1048
1049 return false;
1050 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001051
1052 StringRef getToken() const {
1053 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001054 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001055 }
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001056 bool isRegPair() const { return Kind == k_RegPair; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001057
Craig Topper56c590a2014-04-29 07:58:02 +00001058 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001059 // As a special case until we sort out the definition of div/divu, pretend
1060 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
1061 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1062 RegIdx.Kind & RegKind_GPR)
1063 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001064
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001065 assert(Kind == k_PhysRegister && "Invalid access!");
1066 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +00001067 }
1068
Jack Carterb4dbc172012-09-05 23:34:03 +00001069 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001070 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001071 return Imm.Val;
1072 }
1073
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001074 int64_t getConstantImm() const {
1075 const MCExpr *Val = getImm();
1076 return static_cast<const MCConstantExpr *>(Val)->getValue();
1077 }
1078
1079 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001080 assert((Kind == k_Memory) && "Invalid access!");
1081 return Mem.Base;
1082 }
1083
1084 const MCExpr *getMemOff() const {
1085 assert((Kind == k_Memory) && "Invalid access!");
1086 return Mem.Off;
1087 }
1088
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001089 int64_t getConstantMemOff() const {
1090 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1091 }
1092
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001093 const SmallVectorImpl<unsigned> &getRegList() const {
1094 assert((Kind == k_RegList) && "Invalid access!");
1095 return *(RegList.List);
1096 }
1097
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001098 unsigned getRegPair() const {
1099 assert((Kind == k_RegPair) && "Invalid access!");
1100 return RegIdx.Index;
1101 }
1102
David Blaikie960ea3f2014-06-08 16:18:35 +00001103 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1104 MipsAsmParser &Parser) {
1105 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001106 Op->Tok.Data = Str.data();
1107 Op->Tok.Length = Str.size();
1108 Op->StartLoc = S;
1109 Op->EndLoc = S;
1110 return Op;
1111 }
1112
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001113 /// Create a numeric register (e.g. $1). The exact register remains
1114 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001115 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001116 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001117 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001118 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001119 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001120 }
1121
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001122 /// Create a register that is definitely a GPR.
1123 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001124 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001125 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001126 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001127 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001128 }
1129
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001130 /// Create a register that is definitely a FGR.
1131 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001132 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001133 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001134 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001135 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
1136 }
1137
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001138 /// Create a register that is definitely a HWReg.
1139 /// This is typically only used for named registers such as $hwr_cpunum.
1140 static std::unique_ptr<MipsOperand>
1141 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
1142 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1143 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
1144 }
1145
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001146 /// Create a register that is definitely an FCC.
1147 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001148 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001149 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001150 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001151 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
1152 }
1153
1154 /// Create a register that is definitely an ACC.
1155 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001156 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001157 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001158 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001159 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
1160 }
1161
1162 /// Create a register that is definitely an MSA128.
1163 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001164 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001165 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001166 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001167 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
1168 }
1169
1170 /// Create a register that is definitely an MSACtrl.
1171 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001172 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001173 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001174 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001175 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
1176 }
1177
David Blaikie960ea3f2014-06-08 16:18:35 +00001178 static std::unique_ptr<MipsOperand>
1179 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1180 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001181 Op->Imm.Val = Val;
1182 Op->StartLoc = S;
1183 Op->EndLoc = E;
1184 return Op;
1185 }
1186
David Blaikie960ea3f2014-06-08 16:18:35 +00001187 static std::unique_ptr<MipsOperand>
1188 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1189 SMLoc E, MipsAsmParser &Parser) {
1190 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1191 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001192 Op->Mem.Off = Off;
1193 Op->StartLoc = S;
1194 Op->EndLoc = E;
1195 return Op;
1196 }
1197
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001198 static std::unique_ptr<MipsOperand>
1199 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1200 MipsAsmParser &Parser) {
1201 assert (Regs.size() > 0 && "Empty list not allowed");
1202
1203 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001204 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001205 Op->StartLoc = StartLoc;
1206 Op->EndLoc = EndLoc;
1207 return Op;
1208 }
1209
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001210 static std::unique_ptr<MipsOperand>
1211 CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1212 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
1213 Op->RegIdx.Index = RegNo;
1214 Op->StartLoc = S;
1215 Op->EndLoc = E;
1216 return Op;
1217 }
1218
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001219 bool isGPRAsmReg() const {
1220 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001221 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001222 bool isMM16AsmReg() const {
1223 if (!(isRegIdx() && RegIdx.Kind))
1224 return false;
1225 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1226 || RegIdx.Index == 16 || RegIdx.Index == 17);
1227 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001228 bool isMM16AsmRegZero() const {
1229 if (!(isRegIdx() && RegIdx.Kind))
1230 return false;
1231 return (RegIdx.Index == 0 ||
1232 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1233 RegIdx.Index == 17);
1234 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001235 bool isMM16AsmRegMoveP() const {
1236 if (!(isRegIdx() && RegIdx.Kind))
1237 return false;
1238 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1239 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1240 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001241 bool isFGRAsmReg() const {
1242 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1243 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001244 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001245 bool isHWRegsAsmReg() const {
1246 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001247 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001248 bool isCCRAsmReg() const {
1249 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001250 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001251 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001252 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1253 return false;
1254 if (!AsmParser.hasEightFccRegisters())
1255 return RegIdx.Index == 0;
1256 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001257 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001258 bool isACCAsmReg() const {
1259 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001260 }
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001261 bool isCOP0AsmReg() const {
1262 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1263 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001264 bool isCOP2AsmReg() const {
1265 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001266 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001267 bool isCOP3AsmReg() const {
1268 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1269 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001270 bool isMSA128AsmReg() const {
1271 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001272 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001273 bool isMSACtrlAsmReg() const {
1274 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001275 }
1276
Jack Carterb4dbc172012-09-05 23:34:03 +00001277 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001278 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001279 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001280 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001281
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001282 virtual ~MipsOperand() {
1283 switch (Kind) {
1284 case k_Immediate:
1285 break;
1286 case k_Memory:
1287 delete Mem.Base;
1288 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001289 case k_RegList:
1290 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001291 case k_PhysRegister:
1292 case k_RegisterIndex:
1293 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001294 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001295 break;
1296 }
1297 }
1298
Craig Topper56c590a2014-04-29 07:58:02 +00001299 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001300 switch (Kind) {
1301 case k_Immediate:
1302 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001303 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001304 OS << ">";
1305 break;
1306 case k_Memory:
1307 OS << "Mem<";
1308 Mem.Base->print(OS);
1309 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001310 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001311 OS << ">";
1312 break;
1313 case k_PhysRegister:
1314 OS << "PhysReg<" << PhysReg.Num << ">";
1315 break;
1316 case k_RegisterIndex:
1317 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1318 break;
1319 case k_Token:
1320 OS << Tok.Data;
1321 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001322 case k_RegList:
1323 OS << "RegList< ";
1324 for (auto Reg : (*RegList.List))
1325 OS << Reg << " ";
1326 OS << ">";
1327 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001328 case k_RegPair:
1329 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1330 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001331 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001332 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001333}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001334} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001335
Jack Carter9e65aa32013-03-22 00:05:30 +00001336namespace llvm {
1337extern const MCInstrDesc MipsInsts[];
1338}
1339static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1340 return MipsInsts[Opcode];
1341}
1342
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001343static bool hasShortDelaySlot(unsigned Opcode) {
1344 switch (Opcode) {
1345 case Mips::JALS_MM:
1346 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001347 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001348 case Mips::BGEZALS_MM:
1349 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001350 return true;
1351 default:
1352 return false;
1353 }
1354}
1355
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001356static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1357 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1358 return &SRExpr->getSymbol();
1359 }
1360
1361 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1362 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1363 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1364
1365 if (LHSSym)
1366 return LHSSym;
1367
1368 if (RHSSym)
1369 return RHSSym;
1370
1371 return nullptr;
1372 }
1373
1374 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1375 return getSingleMCSymbol(UExpr->getSubExpr());
1376
1377 return nullptr;
1378}
1379
1380static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1381 if (isa<MCSymbolRefExpr>(Expr))
1382 return 1;
1383
1384 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1385 return countMCSymbolRefExpr(BExpr->getLHS()) +
1386 countMCSymbolRefExpr(BExpr->getRHS());
1387
1388 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1389 return countMCSymbolRefExpr(UExpr->getSubExpr());
1390
1391 return 0;
1392}
1393
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001394namespace {
1395void emitRX(unsigned Opcode, unsigned Reg0, MCOperand Op1, SMLoc IDLoc,
1396 SmallVectorImpl<MCInst> &Instructions) {
1397 MCInst tmpInst;
1398 tmpInst.setOpcode(Opcode);
1399 tmpInst.addOperand(MCOperand::createReg(Reg0));
1400 tmpInst.addOperand(Op1);
1401 tmpInst.setLoc(IDLoc);
1402 Instructions.push_back(tmpInst);
1403}
1404
1405void emitRI(unsigned Opcode, unsigned Reg0, int32_t Imm, SMLoc IDLoc,
1406 SmallVectorImpl<MCInst> &Instructions) {
1407 emitRX(Opcode, Reg0, MCOperand::createImm(Imm), IDLoc, Instructions);
1408}
1409
1410void emitRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, SMLoc IDLoc,
1411 SmallVectorImpl<MCInst> &Instructions) {
1412 emitRX(Opcode, Reg0, MCOperand::createReg(Reg1), IDLoc, Instructions);
1413}
1414
1415void emitII(unsigned Opcode, int16_t Imm1, int16_t Imm2, SMLoc IDLoc,
1416 SmallVectorImpl<MCInst> &Instructions) {
1417 MCInst tmpInst;
1418 tmpInst.setOpcode(Opcode);
1419 tmpInst.addOperand(MCOperand::createImm(Imm1));
1420 tmpInst.addOperand(MCOperand::createImm(Imm2));
1421 tmpInst.setLoc(IDLoc);
1422 Instructions.push_back(tmpInst);
1423}
1424
1425void emitR(unsigned Opcode, unsigned Reg0, SMLoc IDLoc,
1426 SmallVectorImpl<MCInst> &Instructions) {
1427 MCInst tmpInst;
1428 tmpInst.setOpcode(Opcode);
1429 tmpInst.addOperand(MCOperand::createReg(Reg0));
1430 tmpInst.setLoc(IDLoc);
1431 Instructions.push_back(tmpInst);
1432}
1433
1434void emitRRX(unsigned Opcode, unsigned Reg0, unsigned Reg1, MCOperand Op2,
1435 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1436 MCInst tmpInst;
1437 tmpInst.setOpcode(Opcode);
1438 tmpInst.addOperand(MCOperand::createReg(Reg0));
1439 tmpInst.addOperand(MCOperand::createReg(Reg1));
1440 tmpInst.addOperand(Op2);
1441 tmpInst.setLoc(IDLoc);
1442 Instructions.push_back(tmpInst);
1443}
1444
1445void emitRRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, unsigned Reg2,
1446 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1447 emitRRX(Opcode, Reg0, Reg1, MCOperand::createReg(Reg2), IDLoc,
1448 Instructions);
1449}
1450
1451void emitRRI(unsigned Opcode, unsigned Reg0, unsigned Reg1, int16_t Imm,
1452 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1453 emitRRX(Opcode, Reg0, Reg1, MCOperand::createImm(Imm), IDLoc,
1454 Instructions);
1455}
1456
1457void emitAppropriateDSLL(unsigned DstReg, unsigned SrcReg, int16_t ShiftAmount,
1458 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1459 if (ShiftAmount >= 32) {
1460 emitRRI(Mips::DSLL32, DstReg, SrcReg, ShiftAmount - 32, IDLoc,
1461 Instructions);
1462 return;
1463 }
1464
1465 emitRRI(Mips::DSLL, DstReg, SrcReg, ShiftAmount, IDLoc, Instructions);
1466}
1467} // end anonymous namespace.
1468
Jack Carter9e65aa32013-03-22 00:05:30 +00001469bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001470 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001471 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001472 bool ExpandedJalSym = false;
Daniel Sandersa771fef2014-03-24 14:05:39 +00001473
Jack Carter9e65aa32013-03-22 00:05:30 +00001474 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001475
1476 if (MCID.isBranch() || MCID.isCall()) {
1477 const unsigned Opcode = Inst.getOpcode();
1478 MCOperand Offset;
1479
1480 switch (Opcode) {
1481 default:
1482 break;
Kai Nackee0245392015-01-27 19:11:28 +00001483 case Mips::BBIT0:
1484 case Mips::BBIT032:
1485 case Mips::BBIT1:
1486 case Mips::BBIT132:
1487 assert(hasCnMips() && "instruction only valid for octeon cpus");
1488 // Fall through
1489
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001490 case Mips::BEQ:
1491 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001492 case Mips::BEQ_MM:
1493 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001494 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001495 Offset = Inst.getOperand(2);
1496 if (!Offset.isImm())
1497 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001498 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001499 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001500 if (OffsetToAlignment(Offset.getImm(),
1501 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001502 return Error(IDLoc, "branch to misaligned address");
1503 break;
1504 case Mips::BGEZ:
1505 case Mips::BGTZ:
1506 case Mips::BLEZ:
1507 case Mips::BLTZ:
1508 case Mips::BGEZAL:
1509 case Mips::BLTZAL:
1510 case Mips::BC1F:
1511 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001512 case Mips::BGEZ_MM:
1513 case Mips::BGTZ_MM:
1514 case Mips::BLEZ_MM:
1515 case Mips::BLTZ_MM:
1516 case Mips::BGEZAL_MM:
1517 case Mips::BLTZAL_MM:
1518 case Mips::BC1F_MM:
1519 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001520 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001521 Offset = Inst.getOperand(1);
1522 if (!Offset.isImm())
1523 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001524 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001525 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001526 if (OffsetToAlignment(Offset.getImm(),
1527 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001528 return Error(IDLoc, "branch to misaligned address");
1529 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001530 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001531 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001532 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001533 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001534 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1535 Offset = Inst.getOperand(1);
1536 if (!Offset.isImm())
1537 break; // We'll deal with this situation later on when applying fixups.
Craig Topper55b1f292015-10-10 20:17:07 +00001538 if (!isInt<8>(Offset.getImm()))
Jozef Kolek9761e962015-01-12 12:03:34 +00001539 return Error(IDLoc, "branch target out of range");
1540 if (OffsetToAlignment(Offset.getImm(), 2LL))
1541 return Error(IDLoc, "branch to misaligned address");
1542 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001543 }
1544 }
1545
Daniel Sandersa84989a2014-06-16 13:25:35 +00001546 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1547 // We still accept it but it is a normal nop.
1548 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1549 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1550 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1551 "nop instruction");
1552 }
1553
Kai Nackee0245392015-01-27 19:11:28 +00001554 if (hasCnMips()) {
1555 const unsigned Opcode = Inst.getOpcode();
1556 MCOperand Opnd;
1557 int Imm;
1558
1559 switch (Opcode) {
1560 default:
1561 break;
1562
1563 case Mips::BBIT0:
1564 case Mips::BBIT032:
1565 case Mips::BBIT1:
1566 case Mips::BBIT132:
1567 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1568 // The offset is handled above
1569 Opnd = Inst.getOperand(1);
1570 if (!Opnd.isImm())
1571 return Error(IDLoc, "expected immediate operand kind");
1572 Imm = Opnd.getImm();
1573 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1574 Opcode == Mips::BBIT1 ? 63 : 31))
1575 return Error(IDLoc, "immediate operand value out of range");
1576 if (Imm > 31) {
1577 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1578 : Mips::BBIT132);
1579 Inst.getOperand(1).setImm(Imm - 32);
1580 }
1581 break;
1582
1583 case Mips::CINS:
1584 case Mips::CINS32:
1585 case Mips::EXTS:
1586 case Mips::EXTS32:
1587 assert(MCID.getNumOperands() == 4 && "unexpected number of operands");
1588 // Check length
1589 Opnd = Inst.getOperand(3);
1590 if (!Opnd.isImm())
1591 return Error(IDLoc, "expected immediate operand kind");
1592 Imm = Opnd.getImm();
1593 if (Imm < 0 || Imm > 31)
1594 return Error(IDLoc, "immediate operand value out of range");
1595 // Check position
1596 Opnd = Inst.getOperand(2);
1597 if (!Opnd.isImm())
1598 return Error(IDLoc, "expected immediate operand kind");
1599 Imm = Opnd.getImm();
1600 if (Imm < 0 || Imm > (Opcode == Mips::CINS ||
1601 Opcode == Mips::EXTS ? 63 : 31))
1602 return Error(IDLoc, "immediate operand value out of range");
1603 if (Imm > 31) {
1604 Inst.setOpcode(Opcode == Mips::CINS ? Mips::CINS32 : Mips::EXTS32);
1605 Inst.getOperand(2).setImm(Imm - 32);
1606 }
1607 break;
1608
1609 case Mips::SEQi:
1610 case Mips::SNEi:
1611 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1612 Opnd = Inst.getOperand(2);
1613 if (!Opnd.isImm())
1614 return Error(IDLoc, "expected immediate operand kind");
1615 Imm = Opnd.getImm();
1616 if (!isInt<10>(Imm))
1617 return Error(IDLoc, "immediate operand value out of range");
1618 break;
1619 }
1620 }
1621
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001622 // This expansion is not in a function called by tryExpandInstruction()
1623 // because the pseudo-instruction doesn't have a distinct opcode.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001624 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
1625 inPicMode()) {
1626 warnIfNoMacro(IDLoc);
1627
1628 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
1629
1630 // We can do this expansion if there's only 1 symbol in the argument
1631 // expression.
1632 if (countMCSymbolRefExpr(JalExpr) > 1)
1633 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
1634
1635 // FIXME: This is checking the expression can be handled by the later stages
1636 // of the assembler. We ought to leave it to those later stages but
1637 // we can't do that until we stop evaluateRelocExpr() rewriting the
1638 // expressions into non-equivalent forms.
1639 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
1640
1641 // FIXME: Add support for label+offset operands (currently causes an error).
1642 // FIXME: Add support for forward-declared local symbols.
1643 // FIXME: Add expansion for when the LargeGOT option is enabled.
1644 if (JalSym->isInSection() || JalSym->isTemporary()) {
1645 if (isABI_O32()) {
1646 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001647 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001648 // R_(MICRO)MIPS_GOT16 label
1649 // addiu $25, $25, 0
1650 // R_(MICRO)MIPS_LO16 label
1651 // jalr $25
1652 const MCExpr *Got16RelocExpr = evaluateRelocExpr(JalExpr, "got");
1653 const MCExpr *Lo16RelocExpr = evaluateRelocExpr(JalExpr, "lo");
1654
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001655 emitRRX(Mips::LW, Mips::T9, Mips::GP,
1656 MCOperand::createExpr(Got16RelocExpr), IDLoc, Instructions);
1657 emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
1658 MCOperand::createExpr(Lo16RelocExpr), IDLoc, Instructions);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001659 } else if (isABI_N32() || isABI_N64()) {
1660 // If it's a local symbol and the N32/N64 ABIs are being used,
1661 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001662 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001663 // R_(MICRO)MIPS_GOT_DISP label
1664 // jalr $25
1665 const MCExpr *GotDispRelocExpr = evaluateRelocExpr(JalExpr, "got_disp");
1666
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001667 emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
1668 MCOperand::createExpr(GotDispRelocExpr), IDLoc, Instructions);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001669 }
1670 } else {
1671 // If it's an external/weak symbol, we expand to:
1672 // lw/ld $25, 0($gp)
1673 // R_(MICRO)MIPS_CALL16 label
1674 // jalr $25
1675 const MCExpr *Call16RelocExpr = evaluateRelocExpr(JalExpr, "call16");
1676
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001677 emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
1678 MCOperand::createExpr(Call16RelocExpr), IDLoc, Instructions);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001679 }
1680
1681 MCInst JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001682 if (IsCpRestoreSet && inMicroMipsMode())
1683 JalrInst.setOpcode(Mips::JALRS_MM);
1684 else
1685 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001686 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
1687 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
1688
1689 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
1690 // This relocation is supposed to be an optimization hint for the linker
1691 // and is not necessary for correctness.
1692
1693 Inst = JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001694 ExpandedJalSym = true;
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001695 }
1696
Jack Carter9e65aa32013-03-22 00:05:30 +00001697 if (MCID.mayLoad() || MCID.mayStore()) {
1698 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001699 // reference or immediate we may have to expand instructions.
1700 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001701 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001702 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1703 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001704 MCOperand &Op = Inst.getOperand(i);
1705 if (Op.isImm()) {
1706 int MemOffset = Op.getImm();
1707 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001708 // Offset can't exceed 16bit value.
1709 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001710 return false;
1711 }
1712 } else if (Op.isExpr()) {
1713 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001714 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001715 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001716 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001717 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001718 // Expand symbol.
1719 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001720 return false;
1721 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001722 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001723 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001724 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001725 }
1726 }
1727 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001728 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001729 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001730
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001731 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001732 if (MCID.mayLoad()) {
1733 // Try to create 16-bit GP relative load instruction.
1734 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1735 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1736 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1737 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1738 MCOperand &Op = Inst.getOperand(i);
1739 if (Op.isImm()) {
1740 int MemOffset = Op.getImm();
1741 MCOperand &DstReg = Inst.getOperand(0);
1742 MCOperand &BaseReg = Inst.getOperand(1);
Craig Topper55b1f292015-10-10 20:17:07 +00001743 if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&
Jozef Koleke10a02e2015-01-28 17:27:26 +00001744 getContext().getRegisterInfo()->getRegClass(
1745 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00001746 (BaseReg.getReg() == Mips::GP ||
1747 BaseReg.getReg() == Mips::GP_64)) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001748
1749 emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
1750 IDLoc, Instructions);
Jozef Koleke10a02e2015-01-28 17:27:26 +00001751 return false;
1752 }
1753 }
1754 }
1755 } // for
1756 } // if load
1757
1758 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1759
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001760 MCOperand Opnd;
1761 int Imm;
1762
1763 switch (Inst.getOpcode()) {
1764 default:
1765 break;
1766 case Mips::ADDIUS5_MM:
1767 Opnd = Inst.getOperand(2);
1768 if (!Opnd.isImm())
1769 return Error(IDLoc, "expected immediate operand kind");
1770 Imm = Opnd.getImm();
1771 if (Imm < -8 || Imm > 7)
1772 return Error(IDLoc, "immediate operand value out of range");
1773 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001774 case Mips::ADDIUSP_MM:
1775 Opnd = Inst.getOperand(0);
1776 if (!Opnd.isImm())
1777 return Error(IDLoc, "expected immediate operand kind");
1778 Imm = Opnd.getImm();
1779 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1780 Imm % 4 != 0)
1781 return Error(IDLoc, "immediate operand value out of range");
1782 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001783 case Mips::SLL16_MM:
1784 case Mips::SRL16_MM:
1785 Opnd = Inst.getOperand(2);
1786 if (!Opnd.isImm())
1787 return Error(IDLoc, "expected immediate operand kind");
1788 Imm = Opnd.getImm();
1789 if (Imm < 1 || Imm > 8)
1790 return Error(IDLoc, "immediate operand value out of range");
1791 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001792 case Mips::LI16_MM:
1793 Opnd = Inst.getOperand(1);
1794 if (!Opnd.isImm())
1795 return Error(IDLoc, "expected immediate operand kind");
1796 Imm = Opnd.getImm();
1797 if (Imm < -1 || Imm > 126)
1798 return Error(IDLoc, "immediate operand value out of range");
1799 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001800 case Mips::ADDIUR2_MM:
1801 Opnd = Inst.getOperand(2);
1802 if (!Opnd.isImm())
1803 return Error(IDLoc, "expected immediate operand kind");
1804 Imm = Opnd.getImm();
1805 if (!(Imm == 1 || Imm == -1 ||
1806 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1807 return Error(IDLoc, "immediate operand value out of range");
1808 break;
Zoran Jovanovic42b84442014-10-23 11:13:59 +00001809 case Mips::ADDIUR1SP_MM:
1810 Opnd = Inst.getOperand(1);
1811 if (!Opnd.isImm())
1812 return Error(IDLoc, "expected immediate operand kind");
1813 Imm = Opnd.getImm();
1814 if (OffsetToAlignment(Imm, 4LL))
1815 return Error(IDLoc, "misaligned immediate operand value");
1816 if (Imm < 0 || Imm > 255)
1817 return Error(IDLoc, "immediate operand value out of range");
1818 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001819 case Mips::ANDI16_MM:
1820 Opnd = Inst.getOperand(2);
1821 if (!Opnd.isImm())
1822 return Error(IDLoc, "expected immediate operand kind");
1823 Imm = Opnd.getImm();
1824 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1825 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1826 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1827 return Error(IDLoc, "immediate operand value out of range");
1828 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001829 case Mips::LBU16_MM:
1830 Opnd = Inst.getOperand(2);
1831 if (!Opnd.isImm())
1832 return Error(IDLoc, "expected immediate operand kind");
1833 Imm = Opnd.getImm();
1834 if (Imm < -1 || Imm > 14)
1835 return Error(IDLoc, "immediate operand value out of range");
1836 break;
Zoran Jovanovic7ba636c2015-09-17 10:14:09 +00001837 case Mips::TEQ_MM:
1838 case Mips::TGE_MM:
1839 case Mips::TGEU_MM:
1840 case Mips::TLT_MM:
1841 case Mips::TLTU_MM:
1842 case Mips::TNE_MM:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001843 case Mips::SB16_MM:
1844 Opnd = Inst.getOperand(2);
1845 if (!Opnd.isImm())
1846 return Error(IDLoc, "expected immediate operand kind");
1847 Imm = Opnd.getImm();
1848 if (Imm < 0 || Imm > 15)
1849 return Error(IDLoc, "immediate operand value out of range");
1850 break;
1851 case Mips::LHU16_MM:
1852 case Mips::SH16_MM:
1853 Opnd = Inst.getOperand(2);
1854 if (!Opnd.isImm())
1855 return Error(IDLoc, "expected immediate operand kind");
1856 Imm = Opnd.getImm();
1857 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1858 return Error(IDLoc, "immediate operand value out of range");
1859 break;
1860 case Mips::LW16_MM:
1861 case Mips::SW16_MM:
1862 Opnd = Inst.getOperand(2);
1863 if (!Opnd.isImm())
1864 return Error(IDLoc, "expected immediate operand kind");
1865 Imm = Opnd.getImm();
1866 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1867 return Error(IDLoc, "immediate operand value out of range");
1868 break;
Zoran Jovanovic6e6a2c92015-09-16 09:14:35 +00001869 case Mips::PREFX_MM:
Jozef Kolekab6d1cc2014-12-23 19:55:34 +00001870 case Mips::CACHE:
1871 case Mips::PREF:
1872 Opnd = Inst.getOperand(2);
1873 if (!Opnd.isImm())
1874 return Error(IDLoc, "expected immediate operand kind");
1875 Imm = Opnd.getImm();
1876 if (!isUInt<5>(Imm))
1877 return Error(IDLoc, "immediate operand value out of range");
1878 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001879 case Mips::ADDIUPC_MM:
1880 MCOperand Opnd = Inst.getOperand(1);
1881 if (!Opnd.isImm())
1882 return Error(IDLoc, "expected immediate operand kind");
1883 int Imm = Opnd.getImm();
Craig Topper55b1f292015-10-10 20:17:07 +00001884 if ((Imm % 4 != 0) || !isInt<25>(Imm))
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001885 return Error(IDLoc, "immediate operand value out of range");
1886 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001887 }
1888 }
1889
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001890 MacroExpanderResultTy ExpandResult =
1891 tryExpandInstruction(Inst, IDLoc, Instructions);
1892 switch (ExpandResult) {
1893 case MER_NotAMacro:
Jack Carter9e65aa32013-03-22 00:05:30 +00001894 Instructions.push_back(Inst);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001895 break;
1896 case MER_Success:
1897 break;
1898 case MER_Fail:
1899 return true;
1900 }
Jack Carter9e65aa32013-03-22 00:05:30 +00001901
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001902 // If this instruction has a delay slot and .set reorder is active,
1903 // emit a NOP after it.
1904 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
1905 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1906
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001907 if ((Inst.getOpcode() == Mips::JalOneReg ||
1908 Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
1909 isPicAndNotNxxAbi()) {
1910 if (IsCpRestoreSet) {
1911 // We need a NOP between the JALR and the LW:
1912 // If .set reorder has been used, we've already emitted a NOP.
1913 // If .set noreorder has been used, we need to emit a NOP at this point.
1914 if (!AssemblerOptions.back()->isReorder())
1915 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1916
1917 // Load the $gp from the stack.
1918 SmallVector<MCInst, 3> LoadInsts;
1919 createCpRestoreMemOp(true /*IsLoad*/, CpRestoreOffset /*StackOffset*/,
1920 IDLoc, LoadInsts);
1921
1922 for (const MCInst &Inst : LoadInsts)
1923 Instructions.push_back(Inst);
1924
1925 } else
1926 Warning(IDLoc, "no .cprestore used in PIC mode");
1927 }
1928
Jack Carter9e65aa32013-03-22 00:05:30 +00001929 return false;
1930}
1931
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001932MipsAsmParser::MacroExpanderResultTy
1933MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
1934 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001935 switch (Inst.getOpcode()) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001936 default:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001937 return MER_NotAMacro;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001938 case Mips::LoadImm32:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001939 return expandLoadImm(Inst, true, IDLoc, Instructions) ? MER_Fail
1940 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001941 case Mips::LoadImm64:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001942 return expandLoadImm(Inst, false, IDLoc, Instructions) ? MER_Fail
1943 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001944 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001945 case Mips::LoadAddrImm64:
1946 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1947 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
1948 "expected immediate operand kind");
1949
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001950 return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,
1951 Inst.getOperand(1),
1952 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,
1953 Instructions)
1954 ? MER_Fail
1955 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001956 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001957 case Mips::LoadAddrReg64:
1958 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1959 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1960 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
1961 "expected immediate operand kind");
1962
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001963 return expandLoadAddress(Inst.getOperand(0).getReg(),
1964 Inst.getOperand(1).getReg(), Inst.getOperand(2),
1965 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,
1966 Instructions)
1967 ? MER_Fail
1968 : MER_Success;
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001969 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001970 case Mips::B_MMR6_Pseudo:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001971 return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions) ? MER_Fail
1972 : MER_Success;
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001973 case Mips::SWM_MM:
1974 case Mips::LWM_MM:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001975 return expandLoadStoreMultiple(Inst, IDLoc, Instructions) ? MER_Fail
1976 : MER_Success;
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001977 case Mips::JalOneReg:
1978 case Mips::JalTwoReg:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001979 return expandJalWithRegs(Inst, IDLoc, Instructions) ? MER_Fail
1980 : MER_Success;
Toma Tabacue1e460d2015-06-11 10:36:10 +00001981 case Mips::BneImm:
1982 case Mips::BeqImm:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001983 return expandBranchImm(Inst, IDLoc, Instructions) ? MER_Fail : MER_Success;
Toma Tabacu1a108322015-06-17 13:20:24 +00001984 case Mips::BLT:
1985 case Mips::BLE:
1986 case Mips::BGE:
1987 case Mips::BGT:
1988 case Mips::BLTU:
1989 case Mips::BLEU:
1990 case Mips::BGEU:
1991 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00001992 case Mips::BLTL:
1993 case Mips::BLEL:
1994 case Mips::BGEL:
1995 case Mips::BGTL:
1996 case Mips::BLTUL:
1997 case Mips::BLEUL:
1998 case Mips::BGEUL:
1999 case Mips::BGTUL:
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002000 case Mips::BLTImmMacro:
2001 case Mips::BLEImmMacro:
2002 case Mips::BGEImmMacro:
2003 case Mips::BGTImmMacro:
2004 case Mips::BLTUImmMacro:
2005 case Mips::BLEUImmMacro:
2006 case Mips::BGEUImmMacro:
2007 case Mips::BGTUImmMacro:
2008 case Mips::BLTLImmMacro:
2009 case Mips::BLELImmMacro:
2010 case Mips::BGELImmMacro:
2011 case Mips::BGTLImmMacro:
2012 case Mips::BLTULImmMacro:
2013 case Mips::BLEULImmMacro:
2014 case Mips::BGEULImmMacro:
2015 case Mips::BGTULImmMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002016 return expandCondBranches(Inst, IDLoc, Instructions) ? MER_Fail
2017 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002018 case Mips::SDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002019 return expandDiv(Inst, IDLoc, Instructions, false, true) ? MER_Fail
2020 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002021 case Mips::DSDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002022 return expandDiv(Inst, IDLoc, Instructions, true, true) ? MER_Fail
2023 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002024 case Mips::UDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002025 return expandDiv(Inst, IDLoc, Instructions, false, false) ? MER_Fail
2026 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002027 case Mips::DUDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002028 return expandDiv(Inst, IDLoc, Instructions, true, false) ? MER_Fail
2029 : MER_Success;
Daniel Sanders6394ee52015-10-15 14:52:58 +00002030 case Mips::Ulh:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002031 return expandUlh(Inst, true, IDLoc, Instructions) ? MER_Fail : MER_Success;
Toma Tabacud88d79c2015-06-23 14:39:42 +00002032 case Mips::Ulhu:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002033 return expandUlh(Inst, false, IDLoc, Instructions) ? MER_Fail : MER_Success;
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00002034 case Mips::Ulw:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002035 return expandUlw(Inst, IDLoc, Instructions) ? MER_Fail : MER_Success;
2036 case Mips::NORImm:
2037 return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail
2038 : MER_Success;
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002039 case Mips::ADDi:
2040 case Mips::ADDiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002041 case Mips::SLTi:
2042 case Mips::SLTiu:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002043 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2044 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2045 int64_t ImmValue = Inst.getOperand(2).getImm();
2046 if (isInt<16>(ImmValue))
2047 return MER_NotAMacro;
2048 return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail
2049 : MER_Success;
2050 }
2051 return MER_NotAMacro;
2052 case Mips::ANDi:
2053 case Mips::ORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002054 case Mips::XORi:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002055 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2056 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2057 int64_t ImmValue = Inst.getOperand(2).getImm();
2058 if (isUInt<16>(ImmValue))
2059 return MER_NotAMacro;
2060 return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail
2061 : MER_Success;
2062 }
2063 return MER_NotAMacro;
Jack Carterd0bd6422013-04-18 00:41:53 +00002064 }
Jack Carter30a59822012-10-04 04:03:53 +00002065}
Jack Carter92995f12012-10-06 00:53:28 +00002066
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002067bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
2068 SmallVectorImpl<MCInst> &Instructions) {
2069 // Create a JALR instruction which is going to replace the pseudo-JAL.
2070 MCInst JalrInst;
2071 JalrInst.setLoc(IDLoc);
2072 const MCOperand FirstRegOp = Inst.getOperand(0);
2073 const unsigned Opcode = Inst.getOpcode();
2074
2075 if (Opcode == Mips::JalOneReg) {
2076 // jal $rs => jalr $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002077 if (IsCpRestoreSet && inMicroMipsMode()) {
2078 JalrInst.setOpcode(Mips::JALRS16_MM);
2079 JalrInst.addOperand(FirstRegOp);
2080 } else if (inMicroMipsMode()) {
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002081 JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002082 JalrInst.addOperand(FirstRegOp);
2083 } else {
2084 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002085 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002086 JalrInst.addOperand(FirstRegOp);
2087 }
2088 } else if (Opcode == Mips::JalTwoReg) {
2089 // jal $rd, $rs => jalr $rd, $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002090 if (IsCpRestoreSet && inMicroMipsMode())
2091 JalrInst.setOpcode(Mips::JALRS_MM);
2092 else
2093 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002094 JalrInst.addOperand(FirstRegOp);
2095 const MCOperand SecondRegOp = Inst.getOperand(1);
2096 JalrInst.addOperand(SecondRegOp);
2097 }
2098 Instructions.push_back(JalrInst);
2099
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002100 // If .set reorder is active and branch instruction has a delay slot,
2101 // emit a NOP after it.
2102 const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
2103 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) {
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002104 createNop(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc, Instructions);
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002105 }
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002106
2107 return false;
2108}
2109
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002110/// Can the value be represented by a unsigned N-bit value and a shift left?
Benjamin Kramer039b1042015-10-28 13:54:36 +00002111template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002112 unsigned BitNum = findFirstSet(x);
2113
2114 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2115}
2116
2117/// Load (or add) an immediate into a register.
2118///
2119/// @param ImmValue The immediate to load.
2120/// @param DstReg The register that will hold the immediate.
2121/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2122/// for a simple initialization.
2123/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2124/// @param IsAddress True if the immediate represents an address. False if it
2125/// is an integer.
2126/// @param IDLoc Location of the immediate in the source file.
2127/// @param Instructions The instructions emitted by this expansion.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002128bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002129 unsigned SrcReg, bool Is32BitImm,
2130 bool IsAddress, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00002131 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu00e98672015-05-01 12:19:27 +00002132 if (!Is32BitImm && !isGP64bit()) {
2133 Error(IDLoc, "instruction requires a 64-bit architecture");
2134 return true;
2135 }
2136
Daniel Sanders03f9c012015-07-14 12:24:22 +00002137 if (Is32BitImm) {
2138 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2139 // Sign extend up to 64-bit so that the predicates match the hardware
2140 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2141 // true.
2142 ImmValue = SignExtend64<32>(ImmValue);
2143 } else {
2144 Error(IDLoc, "instruction requires a 32-bit immediate");
2145 return true;
2146 }
2147 }
2148
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002149 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2150 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2151
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002152 bool UseSrcReg = false;
2153 if (SrcReg != Mips::NoRegister)
2154 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002155
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002156 unsigned TmpReg = DstReg;
2157 if (UseSrcReg && (DstReg == SrcReg)) {
2158 // At this point we need AT to perform the expansions and we exit if it is
2159 // not available.
2160 unsigned ATReg = getATReg(IDLoc);
2161 if (!ATReg)
2162 return true;
2163 TmpReg = ATReg;
2164 }
2165
Daniel Sanders03f9c012015-07-14 12:24:22 +00002166 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002167 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002168 SrcReg = ZeroReg;
2169
2170 // This doesn't quite follow the usual ABI expectations for N32 but matches
2171 // traditional assembler behaviour. N32 would normally use addiu for both
2172 // integers and addresses.
2173 if (IsAddress && !Is32BitImm) {
2174 emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
2175 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002176 }
2177
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002178 emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
2179 return false;
2180 }
2181
2182 if (isUInt<16>(ImmValue)) {
2183 unsigned TmpReg = DstReg;
2184 if (SrcReg == DstReg) {
2185 TmpReg = getATReg(IDLoc);
2186 if (!TmpReg)
2187 return true;
2188 }
2189
2190 emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002191 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002192 emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2193 return false;
2194 }
2195
2196 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002197 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002198
Toma Tabacu79588102015-04-29 10:19:56 +00002199 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2200 uint16_t Bits15To0 = ImmValue & 0xffff;
2201
Toma Tabacua3d056f2015-05-15 09:42:11 +00002202 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002203 // Traditional behaviour seems to special case this particular value. It's
2204 // not clear why other masks are handled differently.
2205 if (ImmValue == 0xffffffff) {
Daniel Sandersf1ae3672015-08-18 09:55:57 +00002206 emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, Instructions);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002207 emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, Instructions);
2208 if (UseSrcReg)
2209 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2210 return false;
2211 }
2212
2213 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002214 // upper 32 bits.
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002215 emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002216 emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, Instructions);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002217 if (Bits15To0)
2218 emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
2219 if (UseSrcReg)
2220 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2221 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002222 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002223
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002224 emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, Instructions);
2225 if (Bits15To0)
2226 emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002227 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002228 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2229 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002230 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002231
2232 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2233 if (Is32BitImm) {
2234 Error(IDLoc, "instruction requires a 32-bit immediate");
2235 return true;
2236 }
2237
2238 // Traditionally, these immediates are shifted as little as possible and as
2239 // such we align the most significant bit to bit 15 of our temporary.
2240 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2241 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2242 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2243 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
2244 emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, Instructions);
2245 emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, Instructions);
2246
2247 if (UseSrcReg)
2248 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2249
2250 return false;
2251 }
2252
2253 warnIfNoMacro(IDLoc);
2254
2255 // The remaining case is packed with a sequence of dsll and ori with zeros
2256 // being omitted and any neighbouring dsll's being coalesced.
2257 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2258
2259 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2260 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
2261 IDLoc, Instructions))
2262 return false;
2263
2264 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2265 // skip it and defer the shift to the next chunk.
2266 unsigned ShiftCarriedForwards = 16;
2267 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2268 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2269
2270 if (ImmChunk != 0) {
2271 emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
2272 Instructions);
2273 emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, Instructions);
2274 ShiftCarriedForwards = 0;
2275 }
2276
2277 ShiftCarriedForwards += 16;
2278 }
2279 ShiftCarriedForwards -= 16;
2280
2281 // Finish any remaining shifts left by trailing zeros.
2282 if (ShiftCarriedForwards)
2283 emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
2284 Instructions);
2285
2286 if (UseSrcReg)
2287 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2288
Matheus Almeida3813d572014-06-19 14:39:14 +00002289 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002290}
Jack Carter92995f12012-10-06 00:53:28 +00002291
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002292bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
2293 SmallVectorImpl<MCInst> &Instructions) {
2294 const MCOperand &ImmOp = Inst.getOperand(1);
2295 assert(ImmOp.isImm() && "expected immediate operand kind");
2296 const MCOperand &DstRegOp = Inst.getOperand(0);
2297 assert(DstRegOp.isReg() && "expected register operand kind");
2298
2299 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002300 Is32BitImm, false, IDLoc, Instructions))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002301 return true;
2302
2303 return false;
2304}
2305
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002306bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2307 const MCOperand &Offset,
2308 bool Is32BitAddress, SMLoc IDLoc,
2309 SmallVectorImpl<MCInst> &Instructions) {
2310 // la can't produce a usable address when addresses are 64-bit.
2311 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2312 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2313 // We currently can't do this because we depend on the equality
2314 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2315 Error(IDLoc, "la used to load 64-bit address");
2316 // Continue as if we had 'dla' instead.
2317 Is32BitAddress = false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002318 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002319
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002320 // dla requires 64-bit addresses.
2321 if (!Is32BitAddress && !ABI.ArePtrs64bit()) {
2322 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002323 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002324 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002325
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002326 if (!Offset.isImm())
2327 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
2328 Is32BitAddress, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002329
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002330 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
2331 IDLoc, Instructions);
Jack Carter543fdf82012-10-09 23:29:45 +00002332}
2333
Toma Tabacuf712ede2015-06-17 14:31:51 +00002334bool MipsAsmParser::loadAndAddSymbolAddress(
2335 const MCExpr *SymExpr, unsigned DstReg, unsigned SrcReg, bool Is32BitSym,
2336 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002337 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002338
Daniel Sandersd5a89412015-10-05 13:19:29 +00002339 const MCExpr *Symbol = cast<MCExpr>(SymExpr);
2340 const MipsMCExpr *HiExpr = MipsMCExpr::create(
2341 MCSymbolRefExpr::VK_Mips_ABS_HI, Symbol, getContext());
2342 const MipsMCExpr *LoExpr = MipsMCExpr::create(
2343 MCSymbolRefExpr::VK_Mips_ABS_LO, Symbol, getContext());
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002344
Toma Tabacufb9d1252015-06-22 12:08:39 +00002345 bool UseSrcReg = SrcReg != Mips::NoRegister;
2346
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002347 // This is the 64-bit symbol address expansion.
2348 if (ABI.ArePtrs64bit() && isGP64bit()) {
2349 // We always need AT for the 64-bit expansion.
2350 // If it is not available we exit.
2351 unsigned ATReg = getATReg(IDLoc);
2352 if (!ATReg)
2353 return true;
2354
Daniel Sandersd5a89412015-10-05 13:19:29 +00002355 const MipsMCExpr *HighestExpr = MipsMCExpr::create(
2356 MCSymbolRefExpr::VK_Mips_HIGHEST, Symbol, getContext());
2357 const MipsMCExpr *HigherExpr = MipsMCExpr::create(
2358 MCSymbolRefExpr::VK_Mips_HIGHER, Symbol, getContext());
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002359
2360 if (UseSrcReg && (DstReg == SrcReg)) {
2361 // If $rs is the same as $rd:
2362 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
2363 // daddiu $at, $at, %higher(sym)
2364 // dsll $at, $at, 16
2365 // daddiu $at, $at, %hi(sym)
2366 // dsll $at, $at, 16
2367 // daddiu $at, $at, %lo(sym)
2368 // daddu $rd, $at, $rd
2369 emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
2370 Instructions);
2371 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HigherExpr),
2372 IDLoc, Instructions);
2373 emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
2374 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
2375 Instructions);
2376 emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
2377 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
2378 Instructions);
2379 emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, Instructions);
2380
2381 return false;
2382 }
2383
2384 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2385 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
2386 // lui $at, %hi(sym)
2387 // daddiu $rd, $rd, %higher(sym)
2388 // daddiu $at, $at, %lo(sym)
2389 // dsll32 $rd, $rd, 0
2390 // daddu $rd, $rd, $at
2391 // (daddu $rd, $rd, $rs)
2392 emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
2393 Instructions);
2394 emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
2395 Instructions);
2396 emitRRX(Mips::DADDiu, DstReg, DstReg, MCOperand::createExpr(HigherExpr),
2397 IDLoc, Instructions);
2398 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
2399 Instructions);
2400 emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, Instructions);
2401 emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, Instructions);
2402 if (UseSrcReg)
2403 emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, Instructions);
2404
2405 return false;
2406 }
2407
2408 // And now, the 32-bit symbol address expansion:
2409 // If $rs is the same as $rd:
2410 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
2411 // ori $at, $at, %lo(sym)
2412 // addu $rd, $at, $rd
2413 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2414 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
2415 // ori $rd, $rd, %lo(sym)
2416 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00002417 unsigned TmpReg = DstReg;
2418 if (UseSrcReg && (DstReg == SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002419 // If $rs is the same as $rd, we need to use AT.
2420 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00002421 unsigned ATReg = getATReg(IDLoc);
2422 if (!ATReg)
2423 return true;
2424 TmpReg = ATReg;
2425 }
2426
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002427 emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, Instructions);
2428 emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr), IDLoc,
2429 Instructions);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002430
Toma Tabacufb9d1252015-06-22 12:08:39 +00002431 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002432 emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2433 else
2434 assert(DstReg == TmpReg);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002435
Toma Tabacu674825c2015-06-16 12:16:24 +00002436 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002437}
2438
NAKAMURA Takumi2bbc90c2015-01-23 01:02:07 +00002439bool MipsAsmParser::expandUncondBranchMMPseudo(
2440 MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00002441 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
2442 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002443
2444 MCOperand Offset = Inst.getOperand(0);
2445 if (Offset.isExpr()) {
2446 Inst.clear();
2447 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002448 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2449 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2450 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002451 } else {
2452 assert(Offset.isImm() && "expected immediate operand kind");
Craig Topper55b1f292015-10-10 20:17:07 +00002453 if (isInt<11>(Offset.getImm())) {
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002454 // If offset fits into 11 bits then this instruction becomes microMIPS
2455 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00002456 if (inMicroMipsMode())
2457 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002458 } else {
Craig Topper55b1f292015-10-10 20:17:07 +00002459 if (!isInt<17>(Offset.getImm()))
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002460 Error(IDLoc, "branch target out of range");
2461 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
2462 Error(IDLoc, "branch to misaligned address");
2463 Inst.clear();
2464 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002465 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2466 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2467 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002468 }
2469 }
2470 Instructions.push_back(Inst);
2471
Zoran Jovanovicada70912015-09-07 11:56:37 +00002472 // If .set reorder is active and branch instruction has a delay slot,
2473 // emit a NOP after it.
2474 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
2475 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Toma Tabacu234482a2015-03-16 12:03:39 +00002476 createNop(true, IDLoc, Instructions);
2477
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002478 return false;
2479}
2480
Toma Tabacue1e460d2015-06-11 10:36:10 +00002481bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc,
2482 SmallVectorImpl<MCInst> &Instructions) {
2483 const MCOperand &DstRegOp = Inst.getOperand(0);
2484 assert(DstRegOp.isReg() && "expected register operand kind");
2485
2486 const MCOperand &ImmOp = Inst.getOperand(1);
2487 assert(ImmOp.isImm() && "expected immediate operand kind");
2488
2489 const MCOperand &MemOffsetOp = Inst.getOperand(2);
2490 assert(MemOffsetOp.isImm() && "expected immediate operand kind");
2491
2492 unsigned OpCode = 0;
2493 switch(Inst.getOpcode()) {
2494 case Mips::BneImm:
2495 OpCode = Mips::BNE;
2496 break;
2497 case Mips::BeqImm:
2498 OpCode = Mips::BEQ;
2499 break;
2500 default:
2501 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
2502 break;
2503 }
2504
2505 int64_t ImmValue = ImmOp.getImm();
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002506 if (ImmValue == 0)
2507 emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
2508 Instructions);
2509 else {
Toma Tabacue1e460d2015-06-11 10:36:10 +00002510 warnIfNoMacro(IDLoc);
2511
2512 unsigned ATReg = getATReg(IDLoc);
2513 if (!ATReg)
2514 return true;
2515
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002516 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
2517 IDLoc, Instructions))
Toma Tabacue1e460d2015-06-11 10:36:10 +00002518 return true;
2519
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002520 emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, Instructions);
Toma Tabacue1e460d2015-06-11 10:36:10 +00002521 }
2522 return false;
2523}
2524
Jack Carter9e65aa32013-03-22 00:05:30 +00002525void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00002526 SmallVectorImpl<MCInst> &Instructions,
2527 bool isLoad, bool isImmOpnd) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002528 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00002529 const MCExpr *ExprOffset;
2530 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00002531 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002532 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2533 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002534 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002535 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2536 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002537 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00002538 if (isImmOpnd) {
2539 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
2540 ImmOffset = Inst.getOperand(2).getImm();
2541 LoOffset = ImmOffset & 0x0000ffff;
2542 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00002543 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00002544 if (LoOffset & 0x8000)
2545 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00002546 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00002547 ExprOffset = Inst.getOperand(2).getExpr();
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002548 // These are some of the types of expansions we perform here:
2549 // 1) lw $8, sym => lui $8, %hi(sym)
2550 // lw $8, %lo(sym)($8)
2551 // 2) lw $8, offset($9) => lui $8, %hi(offset)
2552 // add $8, $8, $9
2553 // lw $8, %lo(offset)($9)
2554 // 3) lw $8, offset($8) => lui $at, %hi(offset)
2555 // add $at, $at, $8
2556 // lw $8, %lo(offset)($at)
2557 // 4) sw $8, sym => lui $at, %hi(sym)
2558 // sw $8, %lo(sym)($at)
2559 // 5) sw $8, offset($8) => lui $at, %hi(offset)
2560 // add $at, $at, $8
2561 // sw $8, %lo(offset)($at)
2562 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
2563 // ldc1 $f0, %lo(sym)($at)
2564 //
2565 // For load instructions we can use the destination register as a temporary
2566 // if base and dst are different (examples 1 and 2) and if the base register
2567 // is general purpose otherwise we must use $at (example 6) and error if it's
2568 // not available. For stores we must use $at (examples 4 and 5) because we
2569 // must not clobber the source register setting up the offset.
2570 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
2571 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
2572 unsigned RegClassIDOp0 =
2573 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
2574 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
2575 (RegClassIDOp0 == Mips::GPR64RegClassID);
2576 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00002577 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002578 else {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002579 // At this point we need AT to perform the expansions and we exit if it is
2580 // not available.
Toma Tabacu89a712b2015-04-15 10:48:56 +00002581 TmpRegNum = getATReg(IDLoc);
2582 if (!TmpRegNum)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002583 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002584 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002585
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002586 emitRX(Mips::LUi, TmpRegNum,
2587 isImmOpnd ? MCOperand::createImm(HiOffset)
2588 : MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "hi")),
2589 IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00002590 // Add temp register to base.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002591 if (BaseRegNum != Mips::ZERO)
2592 emitRRR(Mips::ADDu, TmpRegNum, TmpRegNum, BaseRegNum, IDLoc, Instructions);
Alp Tokercb402912014-01-24 17:20:08 +00002593 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00002594 // of offset and new base.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002595 emitRRX(Inst.getOpcode(), RegOpNum, TmpRegNum,
2596 isImmOpnd
2597 ? MCOperand::createImm(LoOffset)
2598 : MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "lo")),
2599 IDLoc, Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +00002600}
2601
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002602bool
2603MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2604 SmallVectorImpl<MCInst> &Instructions) {
2605 unsigned OpNum = Inst.getNumOperands();
2606 unsigned Opcode = Inst.getOpcode();
2607 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2608
2609 assert (Inst.getOperand(OpNum - 1).isImm() &&
2610 Inst.getOperand(OpNum - 2).isReg() &&
2611 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2612
2613 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2614 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
2615 Inst.getOperand(OpNum - 2).getReg() == Mips::SP &&
2616 Inst.getOperand(OpNum - 3).getReg() == Mips::RA)
2617 // It can be implemented as SWM16 or LWM16 instruction.
2618 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2619
2620 Inst.setOpcode(NewOpcode);
2621 Instructions.push_back(Inst);
2622 return false;
2623}
2624
Toma Tabacu1a108322015-06-17 13:20:24 +00002625bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
2626 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002627 bool EmittedNoMacroWarning = false;
Toma Tabacu1a108322015-06-17 13:20:24 +00002628 unsigned PseudoOpcode = Inst.getOpcode();
2629 unsigned SrcReg = Inst.getOperand(0).getReg();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002630 const MCOperand &TrgOp = Inst.getOperand(1);
Toma Tabacu1a108322015-06-17 13:20:24 +00002631 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
2632
2633 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002634 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00002635
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002636 unsigned TrgReg;
2637 if (TrgOp.isReg())
2638 TrgReg = TrgOp.getReg();
2639 else if (TrgOp.isImm()) {
2640 warnIfNoMacro(IDLoc);
2641 EmittedNoMacroWarning = true;
2642
2643 TrgReg = getATReg(IDLoc);
2644 if (!TrgReg)
2645 return true;
2646
2647 switch(PseudoOpcode) {
2648 default:
2649 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2650 case Mips::BLTImmMacro:
2651 PseudoOpcode = Mips::BLT;
2652 break;
2653 case Mips::BLEImmMacro:
2654 PseudoOpcode = Mips::BLE;
2655 break;
2656 case Mips::BGEImmMacro:
2657 PseudoOpcode = Mips::BGE;
2658 break;
2659 case Mips::BGTImmMacro:
2660 PseudoOpcode = Mips::BGT;
2661 break;
2662 case Mips::BLTUImmMacro:
2663 PseudoOpcode = Mips::BLTU;
2664 break;
2665 case Mips::BLEUImmMacro:
2666 PseudoOpcode = Mips::BLEU;
2667 break;
2668 case Mips::BGEUImmMacro:
2669 PseudoOpcode = Mips::BGEU;
2670 break;
2671 case Mips::BGTUImmMacro:
2672 PseudoOpcode = Mips::BGTU;
2673 break;
2674 case Mips::BLTLImmMacro:
2675 PseudoOpcode = Mips::BLTL;
2676 break;
2677 case Mips::BLELImmMacro:
2678 PseudoOpcode = Mips::BLEL;
2679 break;
2680 case Mips::BGELImmMacro:
2681 PseudoOpcode = Mips::BGEL;
2682 break;
2683 case Mips::BGTLImmMacro:
2684 PseudoOpcode = Mips::BGTL;
2685 break;
2686 case Mips::BLTULImmMacro:
2687 PseudoOpcode = Mips::BLTUL;
2688 break;
2689 case Mips::BLEULImmMacro:
2690 PseudoOpcode = Mips::BLEUL;
2691 break;
2692 case Mips::BGEULImmMacro:
2693 PseudoOpcode = Mips::BGEUL;
2694 break;
2695 case Mips::BGTULImmMacro:
2696 PseudoOpcode = Mips::BGTUL;
2697 break;
2698 }
2699
2700 if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
2701 false, IDLoc, Instructions))
2702 return true;
2703 }
2704
Toma Tabacu1a108322015-06-17 13:20:24 +00002705 switch (PseudoOpcode) {
2706 case Mips::BLT:
2707 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002708 case Mips::BLTL:
2709 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002710 AcceptsEquality = false;
2711 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002712 IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
2713 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002714 ZeroSrcOpcode = Mips::BGTZ;
2715 ZeroTrgOpcode = Mips::BLTZ;
2716 break;
2717 case Mips::BLE:
2718 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002719 case Mips::BLEL:
2720 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002721 AcceptsEquality = true;
2722 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002723 IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
2724 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002725 ZeroSrcOpcode = Mips::BGEZ;
2726 ZeroTrgOpcode = Mips::BLEZ;
2727 break;
2728 case Mips::BGE:
2729 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002730 case Mips::BGEL:
2731 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002732 AcceptsEquality = true;
2733 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002734 IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
2735 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002736 ZeroSrcOpcode = Mips::BLEZ;
2737 ZeroTrgOpcode = Mips::BGEZ;
2738 break;
2739 case Mips::BGT:
2740 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002741 case Mips::BGTL:
2742 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002743 AcceptsEquality = false;
2744 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002745 IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
2746 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002747 ZeroSrcOpcode = Mips::BLTZ;
2748 ZeroTrgOpcode = Mips::BGTZ;
2749 break;
2750 default:
2751 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2752 }
2753
Toma Tabacu1a108322015-06-17 13:20:24 +00002754 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
2755 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
2756 if (IsSrcRegZero && IsTrgRegZero) {
2757 // FIXME: All of these Opcode-specific if's are needed for compatibility
2758 // with GAS' behaviour. However, they may not generate the most efficient
2759 // code in some circumstances.
2760 if (PseudoOpcode == Mips::BLT) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002761 emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2762 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002763 return false;
2764 }
2765 if (PseudoOpcode == Mips::BLE) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002766 emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2767 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002768 Warning(IDLoc, "branch is always taken");
2769 return false;
2770 }
2771 if (PseudoOpcode == Mips::BGE) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002772 emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2773 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002774 Warning(IDLoc, "branch is always taken");
2775 return false;
2776 }
2777 if (PseudoOpcode == Mips::BGT) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002778 emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2779 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002780 return false;
2781 }
2782 if (PseudoOpcode == Mips::BGTU) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002783 emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
2784 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002785 return false;
2786 }
2787 if (AcceptsEquality) {
2788 // If both registers are $0 and the pseudo-branch accepts equality, it
2789 // will always be taken, so we emit an unconditional branch.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002790 emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
2791 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002792 Warning(IDLoc, "branch is always taken");
2793 return false;
2794 }
2795 // If both registers are $0 and the pseudo-branch does not accept
2796 // equality, it will never be taken, so we don't have to emit anything.
2797 return false;
2798 }
2799 if (IsSrcRegZero || IsTrgRegZero) {
2800 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
2801 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
2802 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
2803 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
2804 // the pseudo-branch will never be taken, so we don't emit anything.
2805 // This only applies to unsigned pseudo-branches.
2806 return false;
2807 }
2808 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
2809 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
2810 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
2811 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
2812 // the pseudo-branch will always be taken, so we emit an unconditional
2813 // branch.
2814 // This only applies to unsigned pseudo-branches.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002815 emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
2816 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002817 Warning(IDLoc, "branch is always taken");
2818 return false;
2819 }
2820 if (IsUnsigned) {
2821 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
2822 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
2823 // the pseudo-branch will be taken only when the non-zero register is
2824 // different from 0, so we emit a BNEZ.
2825 //
2826 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
2827 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
2828 // the pseudo-branch will be taken only when the non-zero register is
2829 // equal to 0, so we emit a BEQZ.
2830 //
2831 // Because only BLEU and BGEU branch on equality, we can use the
2832 // AcceptsEquality variable to decide when to emit the BEQZ.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002833 emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
2834 IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
2835 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002836 return false;
2837 }
2838 // If we have a signed pseudo-branch and one of the registers is $0,
2839 // we can use an appropriate compare-to-zero branch. We select which one
2840 // to use in the switch statement above.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002841 emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
2842 IsSrcRegZero ? TrgReg : SrcReg, MCOperand::createExpr(OffsetExpr),
2843 IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002844 return false;
2845 }
2846
2847 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
2848 // expansions. If it is not available, we return.
2849 unsigned ATRegNum = getATReg(IDLoc);
2850 if (!ATRegNum)
2851 return true;
2852
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002853 if (!EmittedNoMacroWarning)
2854 warnIfNoMacro(IDLoc);
Toma Tabacu1a108322015-06-17 13:20:24 +00002855
2856 // SLT fits well with 2 of our 4 pseudo-branches:
2857 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
2858 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
2859 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
2860 // This is accomplished by using a BNEZ with the result of the SLT.
2861 //
2862 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
2863 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
2864 // Because only BGE and BLE branch on equality, we can use the
2865 // AcceptsEquality variable to decide when to emit the BEQZ.
2866 // Note that the order of the SLT arguments doesn't change between
2867 // opposites.
2868 //
2869 // The same applies to the unsigned variants, except that SLTu is used
2870 // instead of SLT.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002871 emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
2872 ReverseOrderSLT ? TrgReg : SrcReg, ReverseOrderSLT ? SrcReg : TrgReg,
2873 IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002874
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002875 emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
2876 : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
2877 ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2878 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002879 return false;
2880}
2881
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002882bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc,
2883 SmallVectorImpl<MCInst> &Instructions,
2884 const bool IsMips64, const bool Signed) {
2885 if (hasMips32r6()) {
2886 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
2887 return false;
2888 }
2889
2890 warnIfNoMacro(IDLoc);
2891
2892 const MCOperand &RsRegOp = Inst.getOperand(0);
2893 assert(RsRegOp.isReg() && "expected register operand kind");
2894 unsigned RsReg = RsRegOp.getReg();
2895
2896 const MCOperand &RtRegOp = Inst.getOperand(1);
2897 assert(RtRegOp.isReg() && "expected register operand kind");
2898 unsigned RtReg = RtRegOp.getReg();
2899 unsigned DivOp;
2900 unsigned ZeroReg;
2901
2902 if (IsMips64) {
2903 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
2904 ZeroReg = Mips::ZERO_64;
2905 } else {
2906 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
2907 ZeroReg = Mips::ZERO;
2908 }
2909
2910 bool UseTraps = useTraps();
2911
2912 if (RsReg == Mips::ZERO || RsReg == Mips::ZERO_64) {
2913 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)
2914 Warning(IDLoc, "dividing zero by zero");
2915 if (IsMips64) {
2916 if (Signed && (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)) {
2917 if (UseTraps) {
2918 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2919 return false;
2920 }
2921
2922 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2923 return false;
2924 }
2925 } else {
2926 emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
2927 return false;
2928 }
2929 }
2930
2931 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
2932 Warning(IDLoc, "division by zero");
2933 if (Signed) {
2934 if (UseTraps) {
2935 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2936 return false;
2937 }
2938
2939 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2940 return false;
2941 }
2942 }
2943
2944 // FIXME: The values for these two BranchTarget variables may be different in
2945 // micromips. These magic numbers need to be removed.
2946 unsigned BranchTargetNoTraps;
2947 unsigned BranchTarget;
2948
2949 if (UseTraps) {
2950 BranchTarget = IsMips64 ? 12 : 8;
2951 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2952 } else {
2953 BranchTarget = IsMips64 ? 20 : 16;
2954 BranchTargetNoTraps = 8;
2955 // Branch to the li instruction.
2956 emitRRI(Mips::BNE, RtReg, ZeroReg, BranchTargetNoTraps, IDLoc,
2957 Instructions);
2958 }
2959
2960 emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
2961
2962 if (!UseTraps)
2963 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2964
2965 if (!Signed) {
2966 emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
2967 return false;
2968 }
2969
2970 unsigned ATReg = getATReg(IDLoc);
2971 if (!ATReg)
2972 return true;
2973
2974 emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, Instructions);
2975 if (IsMips64) {
2976 // Branch to the mflo instruction.
2977 emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
2978 emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, Instructions);
2979 emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, Instructions);
2980 } else {
2981 // Branch to the mflo instruction.
2982 emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
2983 emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, Instructions);
2984 }
2985
2986 if (UseTraps)
2987 emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, Instructions);
2988 else {
2989 // Branch to the mflo instruction.
2990 emitRRI(Mips::BNE, RsReg, ATReg, BranchTargetNoTraps, IDLoc, Instructions);
2991 emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, Instructions);
2992 emitII(Mips::BREAK, 0x6, 0, IDLoc, Instructions);
2993 }
2994 emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
2995 return false;
2996}
2997
Daniel Sanders6394ee52015-10-15 14:52:58 +00002998bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
2999 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacud88d79c2015-06-23 14:39:42 +00003000 if (hasMips32r6() || hasMips64r6()) {
3001 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3002 return false;
3003 }
3004
3005 warnIfNoMacro(IDLoc);
3006
3007 const MCOperand &DstRegOp = Inst.getOperand(0);
3008 assert(DstRegOp.isReg() && "expected register operand kind");
3009
3010 const MCOperand &SrcRegOp = Inst.getOperand(1);
3011 assert(SrcRegOp.isReg() && "expected register operand kind");
3012
3013 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3014 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3015
3016 unsigned DstReg = DstRegOp.getReg();
3017 unsigned SrcReg = SrcRegOp.getReg();
3018 int64_t OffsetValue = OffsetImmOp.getImm();
3019
3020 // NOTE: We always need AT for ULHU, as it is always used as the source
3021 // register for one of the LBu's.
3022 unsigned ATReg = getATReg(IDLoc);
3023 if (!ATReg)
3024 return true;
3025
3026 // When the value of offset+1 does not fit in 16 bits, we have to load the
3027 // offset in AT, (D)ADDu the original source register (if there was one), and
3028 // then use AT as the source register for the 2 generated LBu's.
3029 bool LoadedOffsetInAT = false;
3030 if (!isInt<16>(OffsetValue + 1) || !isInt<16>(OffsetValue)) {
3031 LoadedOffsetInAT = true;
3032
3033 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003034 true, IDLoc, Instructions))
Toma Tabacud88d79c2015-06-23 14:39:42 +00003035 return true;
3036
3037 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3038 // because it will make our output more similar to GAS'. For example,
3039 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3040 // instead of just an "ori $1, $9, 32768".
3041 // NOTE: If there is no source register specified in the ULHU, the parser
3042 // will interpret it as $0.
3043 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
3044 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
3045 }
3046
3047 unsigned FirstLbuDstReg = LoadedOffsetInAT ? DstReg : ATReg;
3048 unsigned SecondLbuDstReg = LoadedOffsetInAT ? ATReg : DstReg;
3049 unsigned LbuSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3050
3051 int64_t FirstLbuOffset = 0, SecondLbuOffset = 0;
3052 if (isLittle()) {
3053 FirstLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3054 SecondLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3055 } else {
3056 FirstLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3057 SecondLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3058 }
3059
3060 unsigned SllReg = LoadedOffsetInAT ? DstReg : ATReg;
3061
Daniel Sanders6394ee52015-10-15 14:52:58 +00003062 emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
3063 FirstLbuOffset, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003064
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003065 emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondLbuOffset, IDLoc,
3066 Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003067
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003068 emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003069
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003070 emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003071
3072 return false;
3073}
3074
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003075bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc,
3076 SmallVectorImpl<MCInst> &Instructions) {
3077 if (hasMips32r6() || hasMips64r6()) {
3078 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3079 return false;
3080 }
3081
3082 const MCOperand &DstRegOp = Inst.getOperand(0);
3083 assert(DstRegOp.isReg() && "expected register operand kind");
3084
3085 const MCOperand &SrcRegOp = Inst.getOperand(1);
3086 assert(SrcRegOp.isReg() && "expected register operand kind");
3087
3088 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3089 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3090
3091 unsigned SrcReg = SrcRegOp.getReg();
3092 int64_t OffsetValue = OffsetImmOp.getImm();
3093 unsigned ATReg = 0;
3094
3095 // When the value of offset+3 does not fit in 16 bits, we have to load the
3096 // offset in AT, (D)ADDu the original source register (if there was one), and
3097 // then use AT as the source register for the generated LWL and LWR.
3098 bool LoadedOffsetInAT = false;
3099 if (!isInt<16>(OffsetValue + 3) || !isInt<16>(OffsetValue)) {
3100 ATReg = getATReg(IDLoc);
3101 if (!ATReg)
3102 return true;
3103 LoadedOffsetInAT = true;
3104
3105 warnIfNoMacro(IDLoc);
3106
3107 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003108 true, IDLoc, Instructions))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003109 return true;
3110
3111 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3112 // because it will make our output more similar to GAS'. For example,
3113 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3114 // instead of just an "ori $1, $9, 32768".
3115 // NOTE: If there is no source register specified in the ULW, the parser
3116 // will interpret it as $0.
3117 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
3118 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
3119 }
3120
3121 unsigned FinalSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3122 int64_t LeftLoadOffset = 0, RightLoadOffset = 0;
3123 if (isLittle()) {
3124 LeftLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3125 RightLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3126 } else {
3127 LeftLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3128 RightLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3129 }
3130
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003131 emitRRI(Mips::LWL, DstRegOp.getReg(), FinalSrcReg, LeftLoadOffset, IDLoc,
3132 Instructions);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003133
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003134 emitRRI(Mips::LWR, DstRegOp.getReg(), FinalSrcReg, RightLoadOffset, IDLoc,
3135 Instructions);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003136
3137 return false;
3138}
3139
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003140bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
3141 SmallVectorImpl<MCInst> &Instructions) {
3142
3143 assert (Inst.getNumOperands() == 3 && "Invalid operand count");
3144 assert (Inst.getOperand(0).isReg() &&
3145 Inst.getOperand(1).isReg() &&
3146 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
3147
3148 unsigned ATReg = Mips::NoRegister;
3149 unsigned FinalDstReg = Mips::NoRegister;
3150 unsigned DstReg = Inst.getOperand(0).getReg();
3151 unsigned SrcReg = Inst.getOperand(1).getReg();
3152 int64_t ImmValue = Inst.getOperand(2).getImm();
3153
3154 bool Is32Bit = isInt<32>(ImmValue) || isUInt<32>(ImmValue);
3155
3156 unsigned FinalOpcode = Inst.getOpcode();
3157
3158 if (DstReg == SrcReg) {
3159 ATReg = getATReg(Inst.getLoc());
3160 if (!ATReg)
3161 return true;
3162 FinalDstReg = DstReg;
3163 DstReg = ATReg;
3164 }
3165
3166 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Instructions)) {
3167 switch (FinalOpcode) {
3168 default:
3169 llvm_unreachable("unimplemented expansion");
3170 case (Mips::ADDi):
3171 FinalOpcode = Mips::ADD;
3172 break;
3173 case (Mips::ADDiu):
3174 FinalOpcode = Mips::ADDu;
3175 break;
3176 case (Mips::ANDi):
3177 FinalOpcode = Mips::AND;
3178 break;
3179 case (Mips::NORImm):
3180 FinalOpcode = Mips::NOR;
3181 break;
3182 case (Mips::ORi):
3183 FinalOpcode = Mips::OR;
3184 break;
3185 case (Mips::SLTi):
3186 FinalOpcode = Mips::SLT;
3187 break;
3188 case (Mips::SLTiu):
3189 FinalOpcode = Mips::SLTu;
3190 break;
3191 case (Mips::XORi):
3192 FinalOpcode = Mips::XOR;
3193 break;
3194 }
3195
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003196 if (FinalDstReg == Mips::NoRegister)
3197 emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, Instructions);
3198 else
3199 emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc,
3200 Instructions);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003201 return false;
3202 }
3203 return true;
3204}
3205
Toma Tabacu234482a2015-03-16 12:03:39 +00003206void MipsAsmParser::createNop(bool hasShortDelaySlot, SMLoc IDLoc,
3207 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003208 if (hasShortDelaySlot)
3209 emitRR(Mips::MOVE16_MM, Mips::ZERO, Mips::ZERO, IDLoc, Instructions);
3210 else
3211 emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, Instructions);
Toma Tabacu234482a2015-03-16 12:03:39 +00003212}
3213
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003214void MipsAsmParser::createAddu(unsigned DstReg, unsigned SrcReg,
Toma Tabacu0b3e9782015-06-23 14:00:54 +00003215 unsigned TrgReg, bool Is64Bit,
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003216 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanders03f9c012015-07-14 12:24:22 +00003217 emitRRR(Is64Bit ? Mips::DADDu : Mips::ADDu, DstReg, SrcReg, TrgReg, SMLoc(),
3218 Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003219}
3220
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003221void MipsAsmParser::createCpRestoreMemOp(
3222 bool IsLoad, int StackOffset, SMLoc IDLoc,
3223 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003224 // If the offset can not fit into 16 bits, we need to expand.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003225 if (!isInt<16>(StackOffset)) {
3226 MCInst MemInst;
3227 MemInst.setOpcode(IsLoad ? Mips::LW : Mips::SW);
3228 MemInst.addOperand(MCOperand::createReg(Mips::GP));
3229 MemInst.addOperand(MCOperand::createReg(Mips::SP));
3230 MemInst.addOperand(MCOperand::createImm(StackOffset));
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003231 expandMemInst(MemInst, IDLoc, Instructions, IsLoad, true /*HasImmOpnd*/);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003232 return;
3233 }
3234
3235 emitRRI(IsLoad ? Mips::LW : Mips::SW, Mips::GP, Mips::SP, StackOffset, IDLoc,
3236 Instructions);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003237}
3238
Matheus Almeida595fcab2014-06-11 15:05:56 +00003239unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
3240 // As described by the Mips32r2 spec, the registers Rd and Rs for
3241 // jalr.hb must be different.
3242 unsigned Opcode = Inst.getOpcode();
3243
3244 if (Opcode == Mips::JALR_HB &&
3245 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
3246 return Match_RequiresDifferentSrcAndDst;
3247
3248 return Match_Success;
3249}
3250
Daniel Sanders52da7af2015-11-06 12:11:03 +00003251static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
3252 uint64_t ErrorInfo) {
3253 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
3254 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
3255 if (ErrorLoc == SMLoc())
3256 return Loc;
3257 return ErrorLoc;
3258 }
3259 return Loc;
3260}
3261
David Blaikie960ea3f2014-06-08 16:18:35 +00003262bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3263 OperandVector &Operands,
3264 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003265 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00003266 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00003267
Jack Carterb4dbc172012-09-05 23:34:03 +00003268 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00003269 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00003270 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003271 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00003272
3273 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003274 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003275 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00003276 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00003277 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00003278 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00003279 return false;
3280 }
3281 case Match_MissingFeature:
3282 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
3283 return true;
3284 case Match_InvalidOperand: {
3285 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00003286 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003287 if (ErrorInfo >= Operands.size())
3288 return Error(IDLoc, "too few operands for instruction");
3289
Daniel Sanders52da7af2015-11-06 12:11:03 +00003290 ErrorLoc = Operands[ErrorInfo]->getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00003291 if (ErrorLoc == SMLoc())
3292 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00003293 }
3294
3295 return Error(ErrorLoc, "invalid operand for instruction");
3296 }
3297 case Match_MnemonicFail:
3298 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00003299 case Match_RequiresDifferentSrcAndDst:
3300 return Error(IDLoc, "source and destination must be different");
Daniel Sanders52da7af2015-11-06 12:11:03 +00003301 case Match_Immz:
3302 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
Daniel Sandersea4f6532015-11-06 12:22:31 +00003303 case Match_UImm2_0:
3304 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3305 "expected 2-bit unsigned immediate");
3306 case Match_UImm2_1:
3307 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3308 "expected immediate in range 1 .. 4");
Jack Carterb4dbc172012-09-05 23:34:03 +00003309 }
Craig Topper589ceee2015-01-03 08:16:34 +00003310
3311 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00003312}
3313
Toma Tabacud9d344b2015-04-27 14:05:04 +00003314void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
3315 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
3316 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
3317 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003318}
3319
Toma Tabacu81496c12015-05-20 08:54:45 +00003320void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
3321 if (!AssemblerOptions.back()->isMacro())
3322 Warning(Loc, "macro instruction expanded into multiple instructions");
3323}
3324
Daniel Sandersef638fe2014-10-03 15:37:37 +00003325void
3326MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
3327 SMRange Range, bool ShowColors) {
3328 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00003329 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00003330 ShowColors);
3331}
3332
Jack Carter1ac53222013-02-20 23:11:17 +00003333int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003334 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003335
Vladimir Medic4c299852013-11-06 11:27:05 +00003336 CC = StringSwitch<unsigned>(Name)
3337 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003338 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00003339 .Case("a0", 4)
3340 .Case("a1", 5)
3341 .Case("a2", 6)
3342 .Case("a3", 7)
3343 .Case("v0", 2)
3344 .Case("v1", 3)
3345 .Case("s0", 16)
3346 .Case("s1", 17)
3347 .Case("s2", 18)
3348 .Case("s3", 19)
3349 .Case("s4", 20)
3350 .Case("s5", 21)
3351 .Case("s6", 22)
3352 .Case("s7", 23)
3353 .Case("k0", 26)
3354 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003355 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00003356 .Case("sp", 29)
3357 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003358 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00003359 .Case("ra", 31)
3360 .Case("t0", 8)
3361 .Case("t1", 9)
3362 .Case("t2", 10)
3363 .Case("t3", 11)
3364 .Case("t4", 12)
3365 .Case("t5", 13)
3366 .Case("t6", 14)
3367 .Case("t7", 15)
3368 .Case("t8", 24)
3369 .Case("t9", 25)
3370 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003371
Toma Tabacufda445c2014-09-15 15:33:01 +00003372 if (!(isABI_N32() || isABI_N64()))
3373 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003374
Daniel Sandersef638fe2014-10-03 15:37:37 +00003375 if (12 <= CC && CC <= 15) {
3376 // Name is one of t4-t7
3377 AsmToken RegTok = getLexer().peekTok();
3378 SMRange RegRange = RegTok.getLocRange();
3379
3380 StringRef FixedName = StringSwitch<StringRef>(Name)
3381 .Case("t4", "t0")
3382 .Case("t5", "t1")
3383 .Case("t6", "t2")
3384 .Case("t7", "t3")
3385 .Default("");
3386 assert(FixedName != "" && "Register name is not one of t4-t7.");
3387
3388 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
3389 "Did you mean $" + FixedName + "?", RegRange);
3390 }
3391
Toma Tabacufda445c2014-09-15 15:33:01 +00003392 // Although SGI documentation just cuts out t0-t3 for n32/n64,
3393 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
3394 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
3395 if (8 <= CC && CC <= 11)
3396 CC += 4;
3397
3398 if (CC == -1)
3399 CC = StringSwitch<unsigned>(Name)
3400 .Case("a4", 8)
3401 .Case("a5", 9)
3402 .Case("a6", 10)
3403 .Case("a7", 11)
3404 .Case("kt0", 26)
3405 .Case("kt1", 27)
3406 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003407
3408 return CC;
3409}
Jack Carterd0bd6422013-04-18 00:41:53 +00003410
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003411int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
3412 int CC;
3413
3414 CC = StringSwitch<unsigned>(Name)
3415 .Case("hwr_cpunum", 0)
3416 .Case("hwr_synci_step", 1)
3417 .Case("hwr_cc", 2)
3418 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00003419 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003420 .Default(-1);
3421
3422 return CC;
3423}
3424
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003425int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003426
Jack Cartera63b16a2012-09-07 00:23:42 +00003427 if (Name[0] == 'f') {
3428 StringRef NumString = Name.substr(1);
3429 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003430 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003431 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003432 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00003433 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003434 return IntVal;
3435 }
3436 return -1;
3437}
Jack Cartera63b16a2012-09-07 00:23:42 +00003438
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003439int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
3440
3441 if (Name.startswith("fcc")) {
3442 StringRef NumString = Name.substr(3);
3443 unsigned IntVal;
3444 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003445 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003446 if (IntVal > 7) // There are only 8 fcc registers.
3447 return -1;
3448 return IntVal;
3449 }
3450 return -1;
3451}
3452
3453int MipsAsmParser::matchACRegisterName(StringRef Name) {
3454
Akira Hatanaka274d24c2013-08-14 01:15:52 +00003455 if (Name.startswith("ac")) {
3456 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003457 unsigned IntVal;
3458 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003459 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003460 if (IntVal > 3) // There are only 3 acc registers.
3461 return -1;
3462 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00003463 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003464 return -1;
3465}
Jack Carterd0bd6422013-04-18 00:41:53 +00003466
Jack Carter5dc8ac92013-09-25 23:50:44 +00003467int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
3468 unsigned IntVal;
3469
3470 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
3471 return -1;
3472
3473 if (IntVal > 31)
3474 return -1;
3475
3476 return IntVal;
3477}
3478
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003479int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
3480 int CC;
3481
3482 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00003483 .Case("msair", 0)
3484 .Case("msacsr", 1)
3485 .Case("msaaccess", 2)
3486 .Case("msasave", 3)
3487 .Case("msamodify", 4)
3488 .Case("msarequest", 5)
3489 .Case("msamap", 6)
3490 .Case("msaunmap", 7)
3491 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003492
3493 return CC;
3494}
3495
Toma Tabacu89a712b2015-04-15 10:48:56 +00003496unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00003497 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00003498 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00003499 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00003500 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00003501 return 0;
3502 }
3503 unsigned AT = getReg(
3504 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00003505 return AT;
3506}
Jack Carter0b744b32012-10-04 02:29:46 +00003507
Jack Carterd0bd6422013-04-18 00:41:53 +00003508unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00003509 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00003510}
3511
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003512unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003513 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00003514 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003515}
3516
Jack Carter873c7242013-01-12 01:03:14 +00003517int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003518 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00003519 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00003520 return -1;
3521
Jack Carter873c7242013-01-12 01:03:14 +00003522 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00003523}
3524
Toma Tabacu13964452014-09-04 13:23:44 +00003525bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003526 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00003527 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003528
Jack Carter30a59822012-10-04 04:03:53 +00003529 // Check if the current operand has a custom associated parser, if so, try to
3530 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00003531 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3532 if (ResTy == MatchOperand_Success)
3533 return false;
3534 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3535 // there was a match, but an error occurred, in which case, just return that
3536 // the operand parsing failed.
3537 if (ResTy == MatchOperand_ParseFail)
3538 return true;
3539
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003540 DEBUG(dbgs() << ".. Generic Parser\n");
3541
Jack Carterb4dbc172012-09-05 23:34:03 +00003542 switch (getLexer().getKind()) {
3543 default:
3544 Error(Parser.getTok().getLoc(), "unexpected token in operand");
3545 return true;
3546 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003547 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00003548 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00003549
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003550 // Almost all registers have been parsed by custom parsers. There is only
3551 // one exception to this. $zero (and it's alias $0) will reach this point
3552 // for div, divu, and similar instructions because it is not an operand
3553 // to the instruction definition but an explicit register. Special case
3554 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00003555 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00003556 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003557
Jack Carterd0bd6422013-04-18 00:41:53 +00003558 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00003559 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003560 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00003561 return true;
3562
Jack Carter873c7242013-01-12 01:03:14 +00003563 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00003564 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00003565 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00003566 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003567 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00003568
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003569 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003570 return false;
3571 }
Vladimir Medic4c299852013-11-06 11:27:05 +00003572 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00003573 case AsmToken::LParen:
3574 case AsmToken::Minus:
3575 case AsmToken::Plus:
3576 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00003577 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00003578 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003579 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00003580 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003581 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00003582 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00003583 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003584 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003585 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003586 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00003587 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00003588 return true;
3589
Jack Carter873c7242013-01-12 01:03:14 +00003590 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3591
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003592 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00003593 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003594 } // case AsmToken::Percent
3595 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00003596 return true;
3597}
3598
Vladimir Medic4c299852013-11-06 11:27:05 +00003599const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00003600 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00003601 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00003602 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00003603 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00003604 // It's a constant, evaluate reloc value.
3605 int16_t Val;
3606 switch (getVariantKind(RelocStr)) {
3607 case MCSymbolRefExpr::VK_Mips_ABS_LO:
3608 // Get the 1st 16-bits.
3609 Val = MCE->getValue() & 0xffff;
3610 break;
3611 case MCSymbolRefExpr::VK_Mips_ABS_HI:
3612 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
3613 // 16 bits being negative.
3614 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
3615 break;
3616 case MCSymbolRefExpr::VK_Mips_HIGHER:
3617 // Get the 3rd 16-bits.
3618 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
3619 break;
3620 case MCSymbolRefExpr::VK_Mips_HIGHEST:
3621 // Get the 4th 16-bits.
3622 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
3623 break;
3624 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00003625 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00003626 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00003627 return MCConstantExpr::create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00003628 }
3629
Jack Carterb5cf5902013-04-17 00:18:04 +00003630 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003631 // It's a symbol, create a symbolic expression from the symbol.
Toma Tabacu07c97b32015-06-17 10:43:45 +00003632 const MCSymbol *Symbol = &MSRE->getSymbol();
Jack Carterb5cf5902013-04-17 00:18:04 +00003633 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003634 Res = MCSymbolRefExpr::create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003635 return Res;
3636 }
3637
3638 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00003639 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
3640
Sasa Stankovic06c47802014-04-03 10:37:45 +00003641 // Try to create target expression.
3642 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
Jim Grosbach13760bd2015-05-30 01:25:56 +00003643 return MipsMCExpr::create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00003644
Jack Carterd0bd6422013-04-18 00:41:53 +00003645 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
3646 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003647 Res = MCBinaryExpr::create(BE->getOpcode(), LExp, RExp, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003648 return Res;
3649 }
3650
3651 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003652 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003653 Res = MCUnaryExpr::create(UN->getOpcode(), UnExp, getContext());
Jack Carterd0bd6422013-04-18 00:41:53 +00003654 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00003655 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003656 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00003657 return Expr;
3658}
3659
3660bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
3661
3662 switch (Expr->getKind()) {
3663 case MCExpr::Constant:
3664 return true;
3665 case MCExpr::SymbolRef:
3666 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
3667 case MCExpr::Binary:
3668 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
3669 if (!isEvaluated(BE->getLHS()))
3670 return false;
3671 return isEvaluated(BE->getRHS());
3672 }
3673 case MCExpr::Unary:
3674 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00003675 case MCExpr::Target:
3676 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003677 }
Jack Carterb5cf5902013-04-17 00:18:04 +00003678 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00003679}
Jack Carterd0bd6422013-04-18 00:41:53 +00003680
Jack Carterb5cf5902013-04-17 00:18:04 +00003681bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003682 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00003683 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00003684 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00003685 if (Tok.isNot(AsmToken::Identifier))
3686 return true;
3687
Yaron Keren075759a2015-03-30 15:42:36 +00003688 std::string Str = Tok.getIdentifier();
Jack Carterb5cf5902013-04-17 00:18:04 +00003689
Jack Carterd0bd6422013-04-18 00:41:53 +00003690 Parser.Lex(); // Eat the identifier.
3691 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003692 const MCExpr *IdVal;
3693 SMLoc EndLoc;
3694
3695 if (getLexer().getKind() == AsmToken::LParen) {
3696 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003697 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003698 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003699 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003700 const AsmToken &nextTok = Parser.getTok();
3701 if (nextTok.isNot(AsmToken::Identifier))
3702 return true;
3703 Str += "(%";
3704 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00003705 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00003706 if (getLexer().getKind() != AsmToken::LParen)
3707 return true;
3708 } else
3709 break;
3710 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003711 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00003712 return true;
3713
3714 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00003715 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003716
3717 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00003718 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003719
Jack Carterd0bd6422013-04-18 00:41:53 +00003720 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00003721 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003722}
3723
Jack Carterb4dbc172012-09-05 23:34:03 +00003724bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
3725 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003726 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00003727 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003728 if (ResTy == MatchOperand_Success) {
3729 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00003730 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003731 StartLoc = Operand.getStartLoc();
3732 EndLoc = Operand.getEndLoc();
3733
3734 // AFAIK, we only support numeric registers and named GPR's in CFI
3735 // directives.
3736 // Don't worry about eating tokens before failing. Using an unrecognised
3737 // register is a parse error.
3738 if (Operand.isGPRAsmReg()) {
3739 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003740 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003741 }
3742
3743 return (RegNo == (unsigned)-1);
3744 }
3745
3746 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00003747 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00003748}
3749
Jack Carterb5cf5902013-04-17 00:18:04 +00003750bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003751 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00003752 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00003753 bool Result = true;
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003754 unsigned NumOfLParen = 0;
Jack Carterb5cf5902013-04-17 00:18:04 +00003755
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003756 while (getLexer().getKind() == AsmToken::LParen) {
Jack Carterb5cf5902013-04-17 00:18:04 +00003757 Parser.Lex();
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003758 ++NumOfLParen;
3759 }
Jack Carter873c7242013-01-12 01:03:14 +00003760
Jack Carterd0bd6422013-04-18 00:41:53 +00003761 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00003762 default:
3763 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00003764 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00003765 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00003766 case AsmToken::Integer:
3767 case AsmToken::Minus:
3768 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00003769 if (isParenExpr)
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003770 Result = getParser().parseParenExprOfDepth(NumOfLParen, Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00003771 else
3772 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00003773 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00003774 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003775 break;
Jack Carter873c7242013-01-12 01:03:14 +00003776 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00003777 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00003778 }
Jack Carterb5cf5902013-04-17 00:18:04 +00003779 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003780}
3781
David Blaikie960ea3f2014-06-08 16:18:35 +00003782MipsAsmParser::OperandMatchResultTy
3783MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003784 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003785 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00003786 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00003787 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00003788 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003789 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00003790 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00003791 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00003792
Jack Carterb5cf5902013-04-17 00:18:04 +00003793 if (getLexer().getKind() == AsmToken::LParen) {
3794 Parser.Lex();
3795 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003796 }
3797
Jack Carterb5cf5902013-04-17 00:18:04 +00003798 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003799 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00003800 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003801
Jack Carterd0bd6422013-04-18 00:41:53 +00003802 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003803 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003804 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003805 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00003806 SMLoc E =
3807 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003808 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00003809 return MatchOperand_Success;
3810 }
3811 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003812 SMLoc E =
3813 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00003814
Jack Carterd0bd6422013-04-18 00:41:53 +00003815 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00003816 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00003817 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00003818 S, E, *this);
3819 Operands.push_back(
3820 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00003821 return MatchOperand_Success;
3822 }
3823 Error(Parser.getTok().getLoc(), "'(' expected");
3824 return MatchOperand_ParseFail;
3825 }
3826
Jack Carterd0bd6422013-04-18 00:41:53 +00003827 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003828 }
3829
Toma Tabacu13964452014-09-04 13:23:44 +00003830 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003831 if (Res != MatchOperand_Success)
3832 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003833
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003834 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00003835 Error(Parser.getTok().getLoc(), "')' expected");
3836 return MatchOperand_ParseFail;
3837 }
3838
Jack Carter873c7242013-01-12 01:03:14 +00003839 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3840
Jack Carterd0bd6422013-04-18 00:41:53 +00003841 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003842
Craig Topper062a2ba2014-04-25 05:30:21 +00003843 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003844 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00003845
Jack Carterd0bd6422013-04-18 00:41:53 +00003846 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00003847 std::unique_ptr<MipsOperand> op(
3848 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00003849 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00003850 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003851 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00003852 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003853 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
3854 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00003855 if (IdVal->evaluateAsAbsolute(Imm))
3856 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003857 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003858 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00003859 getContext());
3860 }
3861
David Blaikie960ea3f2014-06-08 16:18:35 +00003862 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003863 return MatchOperand_Success;
3864}
3865
David Blaikie960ea3f2014-06-08 16:18:35 +00003866bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003867 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00003868 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00003869 if (Sym) {
3870 SMLoc S = Parser.getTok().getLoc();
3871 const MCExpr *Expr;
3872 if (Sym->isVariable())
3873 Expr = Sym->getVariableValue();
3874 else
3875 return false;
3876 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003877 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00003878 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00003879 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003880 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00003881 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00003882 if (ResTy == MatchOperand_Success) {
3883 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00003884 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00003885 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003886 llvm_unreachable("Should never ParseFail");
3887 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00003888 }
3889 } else if (Expr->getKind() == MCExpr::Constant) {
3890 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00003891 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00003892 Operands.push_back(
3893 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00003894 return true;
3895 }
3896 }
3897 return false;
3898}
Jack Carterd0bd6422013-04-18 00:41:53 +00003899
Jack Carter873c7242013-01-12 01:03:14 +00003900MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003901MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00003902 StringRef Identifier,
3903 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003904 int Index = matchCPURegisterName(Identifier);
3905 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003906 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003907 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3908 return MatchOperand_Success;
3909 }
3910
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003911 Index = matchHWRegsRegisterName(Identifier);
3912 if (Index != -1) {
3913 Operands.push_back(MipsOperand::createHWRegsReg(
3914 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3915 return MatchOperand_Success;
3916 }
3917
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003918 Index = matchFPURegisterName(Identifier);
3919 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003920 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003921 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3922 return MatchOperand_Success;
3923 }
3924
3925 Index = matchFCCRegisterName(Identifier);
3926 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003927 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003928 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3929 return MatchOperand_Success;
3930 }
3931
3932 Index = matchACRegisterName(Identifier);
3933 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003934 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003935 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3936 return MatchOperand_Success;
3937 }
3938
3939 Index = matchMSA128RegisterName(Identifier);
3940 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003941 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003942 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3943 return MatchOperand_Success;
3944 }
3945
3946 Index = matchMSA128CtrlRegisterName(Identifier);
3947 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003948 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003949 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3950 return MatchOperand_Success;
3951 }
3952
3953 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00003954}
3955
3956MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003957MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003958 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00003959 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003960
3961 if (Token.is(AsmToken::Identifier)) {
3962 DEBUG(dbgs() << ".. identifier\n");
3963 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00003964 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00003965 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00003966 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003967 } else if (Token.is(AsmToken::Integer)) {
3968 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00003969 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003970 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
3971 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003972 return MatchOperand_Success;
3973 }
3974
3975 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
3976
3977 return MatchOperand_NoMatch;
3978}
3979
David Blaikie960ea3f2014-06-08 16:18:35 +00003980MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003981MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003982 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00003983 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003984
3985 auto Token = Parser.getTok();
3986
3987 SMLoc S = Token.getLoc();
3988
3989 if (Token.isNot(AsmToken::Dollar)) {
3990 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
3991 if (Token.is(AsmToken::Identifier)) {
3992 if (searchSymbolAlias(Operands))
3993 return MatchOperand_Success;
3994 }
3995 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
3996 return MatchOperand_NoMatch;
3997 }
3998 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003999
Toma Tabacu13964452014-09-04 13:23:44 +00004000 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00004001 if (ResTy == MatchOperand_Success) {
4002 Parser.Lex(); // $
4003 Parser.Lex(); // identifier
4004 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004005 return ResTy;
4006}
4007
4008MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004009MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004010 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004011 switch (getLexer().getKind()) {
4012 default:
4013 return MatchOperand_NoMatch;
4014 case AsmToken::LParen:
4015 case AsmToken::Minus:
4016 case AsmToken::Plus:
4017 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00004018 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004019 case AsmToken::String:
4020 break;
4021 }
4022
4023 const MCExpr *IdVal;
4024 SMLoc S = Parser.getTok().getLoc();
4025 if (getParser().parseExpression(IdVal))
4026 return MatchOperand_ParseFail;
4027
4028 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4029 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
4030 return MatchOperand_Success;
4031}
4032
David Blaikie960ea3f2014-06-08 16:18:35 +00004033MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004034MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004035 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004036 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004037
4038 SMLoc S = getLexer().getLoc();
4039
4040 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00004041 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004042 if (ResTy != MatchOperand_NoMatch)
4043 return ResTy;
4044
Daniel Sanders315386c2014-04-01 10:40:14 +00004045 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00004046 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00004047 if (ResTy != MatchOperand_NoMatch)
4048 return ResTy;
4049
Daniel Sandersffd84362014-04-01 10:41:48 +00004050 const MCExpr *Expr = nullptr;
4051 if (Parser.parseExpression(Expr)) {
4052 // We have no way of knowing if a symbol was consumed so we must ParseFail
4053 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004054 }
Daniel Sandersffd84362014-04-01 10:41:48 +00004055 Operands.push_back(
4056 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004057 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00004058}
4059
Vladimir Medic2b953d02013-10-01 09:48:56 +00004060MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00004061MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004062 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00004063 const MCExpr *IdVal;
4064 // If the first token is '$' we may have register operand.
4065 if (Parser.getTok().is(AsmToken::Dollar))
4066 return MatchOperand_NoMatch;
4067 SMLoc S = Parser.getTok().getLoc();
4068 if (getParser().parseExpression(IdVal))
4069 return MatchOperand_ParseFail;
4070 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00004071 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00004072 int64_t Val = MCE->getValue();
4073 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4074 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00004075 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00004076 return MatchOperand_Success;
4077}
4078
Matheus Almeida779c5932013-11-18 12:32:49 +00004079MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004080MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004081 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00004082 switch (getLexer().getKind()) {
4083 default:
4084 return MatchOperand_NoMatch;
4085 case AsmToken::LParen:
4086 case AsmToken::Plus:
4087 case AsmToken::Minus:
4088 case AsmToken::Integer:
4089 break;
4090 }
4091
4092 const MCExpr *Expr;
4093 SMLoc S = Parser.getTok().getLoc();
4094
4095 if (getParser().parseExpression(Expr))
4096 return MatchOperand_ParseFail;
4097
4098 int64_t Val;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004099 if (!Expr->evaluateAsAbsolute(Val)) {
Matheus Almeida779c5932013-11-18 12:32:49 +00004100 Error(S, "expected immediate value");
4101 return MatchOperand_ParseFail;
4102 }
4103
4104 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
4105 // and because the CPU always adds one to the immediate field, the allowed
4106 // range becomes 1..4. We'll only check the range here and will deal
4107 // with the addition/subtraction when actually decoding/encoding
4108 // the instruction.
4109 if (Val < 1 || Val > 4) {
4110 Error(S, "immediate not in range (1..4)");
4111 return MatchOperand_ParseFail;
4112 }
4113
Jack Carter3b2c96e2014-01-22 23:31:38 +00004114 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004115 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00004116 return MatchOperand_Success;
4117}
4118
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004119MipsAsmParser::OperandMatchResultTy
4120MipsAsmParser::parseRegisterList(OperandVector &Operands) {
4121 MCAsmParser &Parser = getParser();
4122 SmallVector<unsigned, 10> Regs;
4123 unsigned RegNo;
4124 unsigned PrevReg = Mips::NoRegister;
4125 bool RegRange = false;
4126 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4127
4128 if (Parser.getTok().isNot(AsmToken::Dollar))
4129 return MatchOperand_ParseFail;
4130
4131 SMLoc S = Parser.getTok().getLoc();
4132 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
4133 SMLoc E = getLexer().getLoc();
4134 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
4135 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
4136 if (RegRange) {
4137 // Remove last register operand because registers from register range
4138 // should be inserted first.
4139 if (RegNo == Mips::RA) {
4140 Regs.push_back(RegNo);
4141 } else {
4142 unsigned TmpReg = PrevReg + 1;
4143 while (TmpReg <= RegNo) {
4144 if ((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) {
4145 Error(E, "invalid register operand");
4146 return MatchOperand_ParseFail;
4147 }
4148
4149 PrevReg = TmpReg;
4150 Regs.push_back(TmpReg++);
4151 }
4152 }
4153
4154 RegRange = false;
4155 } else {
4156 if ((PrevReg == Mips::NoRegister) && (RegNo != Mips::S0) &&
4157 (RegNo != Mips::RA)) {
4158 Error(E, "$16 or $31 expected");
4159 return MatchOperand_ParseFail;
4160 } else if (((RegNo < Mips::S0) || (RegNo > Mips::S7)) &&
4161 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
4162 Error(E, "invalid register operand");
4163 return MatchOperand_ParseFail;
4164 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
4165 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
4166 Error(E, "consecutive register numbers expected");
4167 return MatchOperand_ParseFail;
4168 }
4169
4170 Regs.push_back(RegNo);
4171 }
4172
4173 if (Parser.getTok().is(AsmToken::Minus))
4174 RegRange = true;
4175
4176 if (!Parser.getTok().isNot(AsmToken::Minus) &&
4177 !Parser.getTok().isNot(AsmToken::Comma)) {
4178 Error(E, "',' or '-' expected");
4179 return MatchOperand_ParseFail;
4180 }
4181
4182 Lex(); // Consume comma or minus
4183 if (Parser.getTok().isNot(AsmToken::Dollar))
4184 break;
4185
4186 PrevReg = RegNo;
4187 }
4188
4189 SMLoc E = Parser.getTok().getLoc();
4190 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4191 parseMemOperand(Operands);
4192 return MatchOperand_Success;
4193}
4194
Zoran Jovanovic2deca342014-12-16 14:59:10 +00004195MipsAsmParser::OperandMatchResultTy
4196MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
4197 MCAsmParser &Parser = getParser();
4198
4199 SMLoc S = Parser.getTok().getLoc();
4200 if (parseAnyRegister(Operands) != MatchOperand_Success)
4201 return MatchOperand_ParseFail;
4202
4203 SMLoc E = Parser.getTok().getLoc();
4204 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
4205 unsigned Reg = Op.getGPR32Reg();
4206 Operands.pop_back();
4207 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
4208 return MatchOperand_Success;
4209}
4210
Zoran Jovanovic41688672015-02-10 16:36:20 +00004211MipsAsmParser::OperandMatchResultTy
4212MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
4213 MCAsmParser &Parser = getParser();
4214 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4215 SmallVector<unsigned, 10> Regs;
4216
4217 if (Parser.getTok().isNot(AsmToken::Dollar))
4218 return MatchOperand_ParseFail;
4219
4220 SMLoc S = Parser.getTok().getLoc();
4221
4222 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4223 return MatchOperand_ParseFail;
4224
4225 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4226 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4227 Regs.push_back(RegNo);
4228
4229 SMLoc E = Parser.getTok().getLoc();
4230 if (Parser.getTok().isNot(AsmToken::Comma)) {
4231 Error(E, "',' expected");
4232 return MatchOperand_ParseFail;
4233 }
4234
4235 // Remove comma.
4236 Parser.Lex();
4237
4238 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4239 return MatchOperand_ParseFail;
4240
4241 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4242 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4243 Regs.push_back(RegNo);
4244
4245 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4246
4247 return MatchOperand_Success;
4248}
4249
Jack Carterdc1e35d2012-09-06 20:00:02 +00004250MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
4251
Vladimir Medic4c299852013-11-06 11:27:05 +00004252 MCSymbolRefExpr::VariantKind VK =
4253 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
4254 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
4255 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
4256 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
4257 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
4258 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
4259 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
4260 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
4261 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
4262 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
4263 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
4264 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
4265 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
4266 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
4267 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
4268 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
4269 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
4270 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00004271 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
4272 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
4273 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
4274 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
4275 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
4276 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00004277 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
4278 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00004279 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00004280
Matheus Almeida2852af82014-04-22 10:15:54 +00004281 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00004282
Jack Carterdc1e35d2012-09-06 20:00:02 +00004283 return VK;
4284}
Jack Cartera63b16a2012-09-07 00:23:42 +00004285
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004286/// Sometimes (i.e. load/stores) the operand may be followed immediately by
4287/// either this.
4288/// ::= '(', register, ')'
4289/// handle it before we iterate so we don't get tripped up by the lack of
4290/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004291bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004292 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004293 if (getLexer().is(AsmToken::LParen)) {
4294 Operands.push_back(
4295 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
4296 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004297 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004298 SMLoc Loc = getLexer().getLoc();
4299 Parser.eatToEndOfStatement();
4300 return Error(Loc, "unexpected token in argument list");
4301 }
4302 if (Parser.getTok().isNot(AsmToken::RParen)) {
4303 SMLoc Loc = getLexer().getLoc();
4304 Parser.eatToEndOfStatement();
4305 return Error(Loc, "unexpected token, expected ')'");
4306 }
4307 Operands.push_back(
4308 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
4309 Parser.Lex();
4310 }
4311 return false;
4312}
4313
4314/// Sometimes (i.e. in MSA) the operand may be followed immediately by
4315/// either one of these.
4316/// ::= '[', register, ']'
4317/// ::= '[', integer, ']'
4318/// handle it before we iterate so we don't get tripped up by the lack of
4319/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004320bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00004321 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004322 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004323 if (getLexer().is(AsmToken::LBrac)) {
4324 Operands.push_back(
4325 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
4326 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004327 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004328 SMLoc Loc = getLexer().getLoc();
4329 Parser.eatToEndOfStatement();
4330 return Error(Loc, "unexpected token in argument list");
4331 }
4332 if (Parser.getTok().isNot(AsmToken::RBrac)) {
4333 SMLoc Loc = getLexer().getLoc();
4334 Parser.eatToEndOfStatement();
4335 return Error(Loc, "unexpected token, expected ']'");
4336 }
4337 Operands.push_back(
4338 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
4339 Parser.Lex();
4340 }
4341 return false;
4342}
4343
David Blaikie960ea3f2014-06-08 16:18:35 +00004344bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
4345 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004346 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004347 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004348
4349 // We have reached first instruction, module directive are now forbidden.
4350 getTargetStreamer().forbidModuleDirective();
4351
Vladimir Medic74593e62013-07-17 15:00:42 +00004352 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00004353 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00004354 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00004355 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00004356 }
Vladimir Medic64828a12013-07-16 10:07:14 +00004357 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004358 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004359
4360 // Read the remaining operands.
4361 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4362 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004363 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004364 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004365 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004366 return Error(Loc, "unexpected token in argument list");
4367 }
Toma Tabacu13964452014-09-04 13:23:44 +00004368 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004369 return true;
4370 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00004371
Jack Carterd0bd6422013-04-18 00:41:53 +00004372 while (getLexer().is(AsmToken::Comma)) {
4373 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00004374 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004375 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004376 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004377 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004378 return Error(Loc, "unexpected token in argument list");
4379 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004380 // Parse bracket and parenthesis suffixes before we iterate
4381 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00004382 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004383 return true;
4384 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00004385 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004386 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00004387 }
4388 }
Jack Carterb4dbc172012-09-05 23:34:03 +00004389 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4390 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004391 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004392 return Error(Loc, "unexpected token in argument list");
4393 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004394 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00004395 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00004396}
4397
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004398bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004399 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004400 SMLoc Loc = getLexer().getLoc();
4401 Parser.eatToEndOfStatement();
4402 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00004403}
4404
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004405bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004406 return Error(Loc, ErrorMsg);
4407}
4408
Jack Carter0b744b32012-10-04 02:29:46 +00004409bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004410 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004411 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00004412
4413 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00004414 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00004415
4416 Parser.Lex(); // Eat "noat".
4417
Jack Carterd0bd6422013-04-18 00:41:53 +00004418 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004419 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004420 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004421 return false;
4422 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004423
4424 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004425 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004426 return false;
4427}
Jack Carterd0bd6422013-04-18 00:41:53 +00004428
Jack Carter0b744b32012-10-04 02:29:46 +00004429bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00004430 // Line can be: ".set at", which sets $at to $1
4431 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00004432 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00004433 Parser.Lex(); // Eat "at".
4434
Jack Carter0b744b32012-10-04 02:29:46 +00004435 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004436 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00004437 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00004438
4439 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004440 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004441 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00004442 }
4443
4444 if (getLexer().isNot(AsmToken::Equal)) {
4445 reportParseError("unexpected token, expected equals sign");
4446 return false;
4447 }
4448 Parser.Lex(); // Eat "=".
4449
4450 if (getLexer().isNot(AsmToken::Dollar)) {
4451 if (getLexer().is(AsmToken::EndOfStatement)) {
4452 reportParseError("no register specified");
4453 return false;
4454 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00004455 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00004456 return false;
4457 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004458 }
4459 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00004460
Toma Tabacu16a74492015-02-13 10:30:57 +00004461 // Find out what "reg" is.
4462 unsigned AtRegNo;
4463 const AsmToken &Reg = Parser.getTok();
4464 if (Reg.is(AsmToken::Identifier)) {
4465 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
4466 } else if (Reg.is(AsmToken::Integer)) {
4467 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00004468 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00004469 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00004470 return false;
4471 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004472
4473 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00004474 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004475 reportParseError("invalid register");
4476 return false;
4477 }
4478 Parser.Lex(); // Eat "reg".
4479
4480 // If this is not the end of the statement, report an error.
4481 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4482 reportParseError("unexpected token, expected end of statement");
4483 return false;
4484 }
4485
4486 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
4487
4488 Parser.Lex(); // Consume the EndOfStatement.
4489 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004490}
4491
4492bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004493 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004494 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004495 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004496 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004497 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004498 return false;
4499 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004500 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00004501 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004502 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004503 return false;
4504}
4505
4506bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004507 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004508 Parser.Lex();
4509 // If this is not the end of the statement, report an error.
4510 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004511 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004512 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00004513 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004514 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00004515 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004516 Parser.Lex(); // Consume the EndOfStatement.
4517 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004518}
4519
4520bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004521 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004522 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004523 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004524 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004525 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004526 return false;
4527 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004528 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00004529 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00004530 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004531 return false;
4532}
4533
4534bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004535 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004536 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004537 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004538 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004539 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004540 return false;
4541 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004542 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00004543 reportParseError("`noreorder' must be set before `nomacro'");
4544 return false;
4545 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004546 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00004547 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00004548 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004549 return false;
4550}
Jack Carterd76b2372013-03-21 21:44:16 +00004551
Daniel Sanders44934432014-08-07 12:03:36 +00004552bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004553 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00004554 Parser.Lex();
4555
4556 // If this is not the end of the statement, report an error.
4557 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004558 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00004559
4560 setFeatureBits(Mips::FeatureMSA, "msa");
4561 getTargetStreamer().emitDirectiveSetMsa();
4562 return false;
4563}
4564
4565bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004566 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00004567 Parser.Lex();
4568
4569 // If this is not the end of the statement, report an error.
4570 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004571 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00004572
4573 clearFeatureBits(Mips::FeatureMSA, "msa");
4574 getTargetStreamer().emitDirectiveSetNoMsa();
4575 return false;
4576}
4577
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004578bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004579 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004580 Parser.Lex(); // Eat "nodsp".
4581
4582 // If this is not the end of the statement, report an error.
4583 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4584 reportParseError("unexpected token, expected end of statement");
4585 return false;
4586 }
4587
4588 clearFeatureBits(Mips::FeatureDSP, "dsp");
4589 getTargetStreamer().emitDirectiveSetNoDsp();
4590 return false;
4591}
4592
Toma Tabacucc2502d2014-11-04 17:18:07 +00004593bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004594 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00004595 Parser.Lex(); // Eat "mips16".
4596
Jack Carter39536722014-01-22 23:08:42 +00004597 // If this is not the end of the statement, report an error.
4598 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004599 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00004600 return false;
4601 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00004602
4603 setFeatureBits(Mips::FeatureMips16, "mips16");
4604 getTargetStreamer().emitDirectiveSetMips16();
4605 Parser.Lex(); // Consume the EndOfStatement.
4606 return false;
4607}
4608
4609bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004610 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00004611 Parser.Lex(); // Eat "nomips16".
4612
4613 // If this is not the end of the statement, report an error.
4614 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4615 reportParseError("unexpected token, expected end of statement");
4616 return false;
4617 }
4618
4619 clearFeatureBits(Mips::FeatureMips16, "mips16");
4620 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00004621 Parser.Lex(); // Consume the EndOfStatement.
4622 return false;
4623}
4624
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004625bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004626 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004627 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004628 // Line can be: .set fp=32
4629 // .set fp=xx
4630 // .set fp=64
4631 Parser.Lex(); // Eat fp token
4632 AsmToken Tok = Parser.getTok();
4633 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004634 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004635 return false;
4636 }
4637 Parser.Lex(); // Eat '=' token.
4638 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004639
4640 if (!parseFpABIValue(FpAbiVal, ".set"))
4641 return false;
4642
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004643 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004644 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004645 return false;
4646 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004647 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004648 Parser.Lex(); // Consume the EndOfStatement.
4649 return false;
4650}
4651
Toma Tabacu32c72aa2015-06-30 09:36:50 +00004652bool MipsAsmParser::parseSetOddSPRegDirective() {
4653 MCAsmParser &Parser = getParser();
4654
4655 Parser.Lex(); // Eat "oddspreg".
4656 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4657 reportParseError("unexpected token, expected end of statement");
4658 return false;
4659 }
4660
4661 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4662 getTargetStreamer().emitDirectiveSetOddSPReg();
4663 return false;
4664}
4665
4666bool MipsAsmParser::parseSetNoOddSPRegDirective() {
4667 MCAsmParser &Parser = getParser();
4668
4669 Parser.Lex(); // Eat "nooddspreg".
4670 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4671 reportParseError("unexpected token, expected end of statement");
4672 return false;
4673 }
4674
4675 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4676 getTargetStreamer().emitDirectiveSetNoOddSPReg();
4677 return false;
4678}
4679
Toma Tabacu9db22db2014-09-09 10:15:38 +00004680bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004681 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00004682 SMLoc Loc = getLexer().getLoc();
4683
4684 Parser.Lex();
4685 if (getLexer().isNot(AsmToken::EndOfStatement))
4686 return reportParseError("unexpected token, expected end of statement");
4687
4688 // Always keep an element on the options "stack" to prevent the user
4689 // from changing the initial options. This is how we remember them.
4690 if (AssemblerOptions.size() == 2)
4691 return reportParseError(Loc, ".set pop with no .set push");
4692
4693 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00004694 setAvailableFeatures(
4695 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
4696 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00004697
4698 getTargetStreamer().emitDirectiveSetPop();
4699 return false;
4700}
4701
4702bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004703 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00004704 Parser.Lex();
4705 if (getLexer().isNot(AsmToken::EndOfStatement))
4706 return reportParseError("unexpected token, expected end of statement");
4707
4708 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00004709 AssemblerOptions.push_back(
4710 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00004711
4712 getTargetStreamer().emitDirectiveSetPush();
4713 return false;
4714}
4715
Toma Tabacu29696502015-06-02 09:48:04 +00004716bool MipsAsmParser::parseSetSoftFloatDirective() {
4717 MCAsmParser &Parser = getParser();
4718 Parser.Lex();
4719 if (getLexer().isNot(AsmToken::EndOfStatement))
4720 return reportParseError("unexpected token, expected end of statement");
4721
4722 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
4723 getTargetStreamer().emitDirectiveSetSoftFloat();
4724 return false;
4725}
4726
4727bool MipsAsmParser::parseSetHardFloatDirective() {
4728 MCAsmParser &Parser = getParser();
4729 Parser.Lex();
4730 if (getLexer().isNot(AsmToken::EndOfStatement))
4731 return reportParseError("unexpected token, expected end of statement");
4732
4733 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
4734 getTargetStreamer().emitDirectiveSetHardFloat();
4735 return false;
4736}
4737
Jack Carterd76b2372013-03-21 21:44:16 +00004738bool MipsAsmParser::parseSetAssignment() {
4739 StringRef Name;
4740 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00004741 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00004742
4743 if (Parser.parseIdentifier(Name))
4744 reportParseError("expected identifier after .set");
4745
4746 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00004747 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00004748 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00004749
Jack Carter3b2c96e2014-01-22 23:31:38 +00004750 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00004751 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00004752
Jim Grosbach6f482002015-05-18 18:43:14 +00004753 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00004754 Sym->setVariableValue(Value);
4755
4756 return false;
4757}
Jack Carterd0bd6422013-04-18 00:41:53 +00004758
Toma Tabacu26647792014-09-09 12:52:14 +00004759bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004760 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00004761 Parser.Lex();
4762 if (getLexer().isNot(AsmToken::EndOfStatement))
4763 return reportParseError("unexpected token, expected end of statement");
4764
4765 // Reset assembler options to their initial values.
Toma Tabacu465acfd2015-06-09 13:33:26 +00004766 setAvailableFeatures(
4767 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
4768 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00004769 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
4770
4771 getTargetStreamer().emitDirectiveSetMips0();
4772 return false;
4773}
4774
Toma Tabacu85618b32014-08-19 14:22:52 +00004775bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004776 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00004777 Parser.Lex();
4778 if (getLexer().isNot(AsmToken::Equal))
4779 return reportParseError("unexpected token, expected equals sign");
4780
4781 Parser.Lex();
4782 StringRef Arch;
4783 if (Parser.parseIdentifier(Arch))
4784 return reportParseError("expected arch identifier");
4785
4786 StringRef ArchFeatureName =
4787 StringSwitch<StringRef>(Arch)
4788 .Case("mips1", "mips1")
4789 .Case("mips2", "mips2")
4790 .Case("mips3", "mips3")
4791 .Case("mips4", "mips4")
4792 .Case("mips5", "mips5")
4793 .Case("mips32", "mips32")
4794 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00004795 .Case("mips32r3", "mips32r3")
4796 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00004797 .Case("mips32r6", "mips32r6")
4798 .Case("mips64", "mips64")
4799 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00004800 .Case("mips64r3", "mips64r3")
4801 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00004802 .Case("mips64r6", "mips64r6")
4803 .Case("cnmips", "cnmips")
4804 .Case("r4000", "mips3") // This is an implementation of Mips3.
4805 .Default("");
4806
4807 if (ArchFeatureName.empty())
4808 return reportParseError("unsupported architecture");
4809
4810 selectArch(ArchFeatureName);
4811 getTargetStreamer().emitDirectiveSetArch(Arch);
4812 return false;
4813}
4814
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004815bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004816 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004817 Parser.Lex();
4818 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004819 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004820
Matheus Almeida2852af82014-04-22 10:15:54 +00004821 switch (Feature) {
4822 default:
4823 llvm_unreachable("Unimplemented feature");
4824 case Mips::FeatureDSP:
4825 setFeatureBits(Mips::FeatureDSP, "dsp");
4826 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004827 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004828 case Mips::FeatureMicroMips:
4829 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004830 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004831 case Mips::FeatureMips1:
4832 selectArch("mips1");
4833 getTargetStreamer().emitDirectiveSetMips1();
4834 break;
4835 case Mips::FeatureMips2:
4836 selectArch("mips2");
4837 getTargetStreamer().emitDirectiveSetMips2();
4838 break;
4839 case Mips::FeatureMips3:
4840 selectArch("mips3");
4841 getTargetStreamer().emitDirectiveSetMips3();
4842 break;
4843 case Mips::FeatureMips4:
4844 selectArch("mips4");
4845 getTargetStreamer().emitDirectiveSetMips4();
4846 break;
4847 case Mips::FeatureMips5:
4848 selectArch("mips5");
4849 getTargetStreamer().emitDirectiveSetMips5();
4850 break;
4851 case Mips::FeatureMips32:
4852 selectArch("mips32");
4853 getTargetStreamer().emitDirectiveSetMips32();
4854 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004855 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004856 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00004857 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004858 break;
Daniel Sanders17793142015-02-18 16:24:50 +00004859 case Mips::FeatureMips32r3:
4860 selectArch("mips32r3");
4861 getTargetStreamer().emitDirectiveSetMips32R3();
4862 break;
4863 case Mips::FeatureMips32r5:
4864 selectArch("mips32r5");
4865 getTargetStreamer().emitDirectiveSetMips32R5();
4866 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004867 case Mips::FeatureMips32r6:
4868 selectArch("mips32r6");
4869 getTargetStreamer().emitDirectiveSetMips32R6();
4870 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004871 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004872 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00004873 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00004874 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004875 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004876 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00004877 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00004878 break;
Daniel Sanders17793142015-02-18 16:24:50 +00004879 case Mips::FeatureMips64r3:
4880 selectArch("mips64r3");
4881 getTargetStreamer().emitDirectiveSetMips64R3();
4882 break;
4883 case Mips::FeatureMips64r5:
4884 selectArch("mips64r5");
4885 getTargetStreamer().emitDirectiveSetMips64R5();
4886 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004887 case Mips::FeatureMips64r6:
4888 selectArch("mips64r6");
4889 getTargetStreamer().emitDirectiveSetMips64R6();
4890 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004891 }
4892 return false;
4893}
4894
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004895bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004896 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004897 if (getLexer().isNot(AsmToken::Comma)) {
4898 SMLoc Loc = getLexer().getLoc();
4899 Parser.eatToEndOfStatement();
4900 return Error(Loc, ErrorStr);
4901 }
4902
Matheus Almeida2852af82014-04-22 10:15:54 +00004903 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004904 return true;
4905}
4906
Daniel Sanderse2982ad2015-09-17 16:08:39 +00004907// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
4908// In this class, it is only used for .cprestore.
4909// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
4910// MipsTargetELFStreamer and MipsAsmParser.
4911bool MipsAsmParser::isPicAndNotNxxAbi() {
4912 return inPicMode() && !(isABI_N32() || isABI_N64());
4913}
4914
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004915bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00004916 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00004917 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004918
Toma Tabacudde4c462014-11-06 10:02:45 +00004919 if (inMips16Mode()) {
4920 reportParseError(".cpload is not supported in Mips16 mode");
4921 return false;
4922 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004923
David Blaikie960ea3f2014-06-08 16:18:35 +00004924 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00004925 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004926 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4927 reportParseError("expected register containing function address");
4928 return false;
4929 }
4930
David Blaikie960ea3f2014-06-08 16:18:35 +00004931 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
4932 if (!RegOpnd.isGPRAsmReg()) {
4933 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004934 return false;
4935 }
4936
Toma Tabacudde4c462014-11-06 10:02:45 +00004937 // If this is not the end of the statement, report an error.
4938 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4939 reportParseError("unexpected token, expected end of statement");
4940 return false;
4941 }
4942
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004943 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004944 return false;
4945}
4946
Daniel Sanderse2982ad2015-09-17 16:08:39 +00004947bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
4948 MCAsmParser &Parser = getParser();
4949
4950 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
4951 // is used in non-PIC mode.
4952
4953 if (inMips16Mode()) {
4954 reportParseError(".cprestore is not supported in Mips16 mode");
4955 return false;
4956 }
4957
4958 // Get the stack offset value.
4959 const MCExpr *StackOffset;
4960 int64_t StackOffsetVal;
4961 if (Parser.parseExpression(StackOffset)) {
4962 reportParseError("expected stack offset value");
4963 return false;
4964 }
4965
4966 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
4967 reportParseError("stack offset is not an absolute expression");
4968 return false;
4969 }
4970
4971 if (StackOffsetVal < 0) {
4972 Warning(Loc, ".cprestore with negative stack offset has no effect");
4973 IsCpRestoreSet = false;
4974 } else {
4975 IsCpRestoreSet = true;
4976 CpRestoreOffset = StackOffsetVal;
4977 }
4978
4979 // If this is not the end of the statement, report an error.
4980 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4981 reportParseError("unexpected token, expected end of statement");
4982 return false;
4983 }
4984
4985 // Store the $gp on the stack.
4986 SmallVector<MCInst, 3> StoreInsts;
4987 createCpRestoreMemOp(false /*IsLoad*/, CpRestoreOffset /*StackOffset*/, Loc,
4988 StoreInsts);
4989
4990 getTargetStreamer().emitDirectiveCpRestore(StoreInsts, CpRestoreOffset);
4991 Parser.Lex(); // Consume the EndOfStatement.
4992 return false;
4993}
4994
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004995bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004996 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004997 unsigned FuncReg;
4998 unsigned Save;
4999 bool SaveIsReg = true;
5000
Matheus Almeida7e815762014-06-18 13:08:59 +00005001 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005002 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005003 if (ResTy == MatchOperand_NoMatch) {
5004 reportParseError("expected register containing function address");
5005 Parser.eatToEndOfStatement();
5006 return false;
5007 }
5008
5009 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5010 if (!FuncRegOpnd.isGPRAsmReg()) {
5011 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
5012 Parser.eatToEndOfStatement();
5013 return false;
5014 }
5015
5016 FuncReg = FuncRegOpnd.getGPR32Reg();
5017 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005018
Toma Tabacu65f10572014-09-16 15:00:52 +00005019 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005020 return true;
5021
Toma Tabacu13964452014-09-04 13:23:44 +00005022 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005023 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00005024 const MCExpr *OffsetExpr;
5025 int64_t OffsetVal;
5026 SMLoc ExprLoc = getLexer().getLoc();
5027
5028 if (Parser.parseExpression(OffsetExpr) ||
5029 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
5030 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00005031 Parser.eatToEndOfStatement();
5032 return false;
5033 }
Daniel Sanders5d796282015-09-21 09:26:55 +00005034
5035 Save = OffsetVal;
5036 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00005037 } else {
5038 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5039 if (!SaveOpnd.isGPRAsmReg()) {
5040 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
5041 Parser.eatToEndOfStatement();
5042 return false;
5043 }
5044 Save = SaveOpnd.getGPR32Reg();
5045 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005046
Toma Tabacu65f10572014-09-16 15:00:52 +00005047 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005048 return true;
5049
Toma Tabacu8874eac2015-02-18 13:46:53 +00005050 const MCExpr *Expr;
5051 if (Parser.parseExpression(Expr)) {
5052 reportParseError("expected expression");
5053 return false;
5054 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005055
Toma Tabacu8874eac2015-02-18 13:46:53 +00005056 if (Expr->getKind() != MCExpr::SymbolRef) {
5057 reportParseError("expected symbol");
5058 return false;
5059 }
5060 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
5061
Daniel Sandersf173dda2015-09-22 10:50:09 +00005062 CpSaveLocation = Save;
5063 CpSaveLocationIsRegister = SaveIsReg;
5064
Toma Tabacu8874eac2015-02-18 13:46:53 +00005065 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
5066 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005067 return false;
5068}
5069
Daniel Sandersf173dda2015-09-22 10:50:09 +00005070bool MipsAsmParser::parseDirectiveCPReturn() {
5071 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
5072 CpSaveLocationIsRegister);
5073 return false;
5074}
5075
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005076bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005077 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005078 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5079 const AsmToken &Tok = Parser.getTok();
5080
5081 if (Tok.getString() == "2008") {
5082 Parser.Lex();
5083 getTargetStreamer().emitDirectiveNaN2008();
5084 return false;
5085 } else if (Tok.getString() == "legacy") {
5086 Parser.Lex();
5087 getTargetStreamer().emitDirectiveNaNLegacy();
5088 return false;
5089 }
5090 }
5091 // If we don't recognize the option passed to the .nan
5092 // directive (e.g. no option or unknown option), emit an error.
5093 reportParseError("invalid option in .nan directive");
5094 return false;
5095}
5096
Jack Carter0b744b32012-10-04 02:29:46 +00005097bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005098 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005099 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00005100 const AsmToken &Tok = Parser.getTok();
5101
5102 if (Tok.getString() == "noat") {
5103 return parseSetNoAtDirective();
5104 } else if (Tok.getString() == "at") {
5105 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00005106 } else if (Tok.getString() == "arch") {
5107 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005108 } else if (Tok.getString() == "fp") {
5109 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005110 } else if (Tok.getString() == "oddspreg") {
5111 return parseSetOddSPRegDirective();
5112 } else if (Tok.getString() == "nooddspreg") {
5113 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005114 } else if (Tok.getString() == "pop") {
5115 return parseSetPopDirective();
5116 } else if (Tok.getString() == "push") {
5117 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00005118 } else if (Tok.getString() == "reorder") {
5119 return parseSetReorderDirective();
5120 } else if (Tok.getString() == "noreorder") {
5121 return parseSetNoReorderDirective();
5122 } else if (Tok.getString() == "macro") {
5123 return parseSetMacroDirective();
5124 } else if (Tok.getString() == "nomacro") {
5125 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00005126 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00005127 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005128 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00005129 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005130 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00005131 getTargetStreamer().emitDirectiveSetNoMicroMips();
5132 Parser.eatToEndOfStatement();
5133 return false;
5134 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005135 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00005136 } else if (Tok.getString() == "mips0") {
5137 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00005138 } else if (Tok.getString() == "mips1") {
5139 return parseSetFeature(Mips::FeatureMips1);
5140 } else if (Tok.getString() == "mips2") {
5141 return parseSetFeature(Mips::FeatureMips2);
5142 } else if (Tok.getString() == "mips3") {
5143 return parseSetFeature(Mips::FeatureMips3);
5144 } else if (Tok.getString() == "mips4") {
5145 return parseSetFeature(Mips::FeatureMips4);
5146 } else if (Tok.getString() == "mips5") {
5147 return parseSetFeature(Mips::FeatureMips5);
5148 } else if (Tok.getString() == "mips32") {
5149 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00005150 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005151 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005152 } else if (Tok.getString() == "mips32r3") {
5153 return parseSetFeature(Mips::FeatureMips32r3);
5154 } else if (Tok.getString() == "mips32r5") {
5155 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005156 } else if (Tok.getString() == "mips32r6") {
5157 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005158 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005159 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005160 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005161 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005162 } else if (Tok.getString() == "mips64r3") {
5163 return parseSetFeature(Mips::FeatureMips64r3);
5164 } else if (Tok.getString() == "mips64r5") {
5165 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005166 } else if (Tok.getString() == "mips64r6") {
5167 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00005168 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005169 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005170 } else if (Tok.getString() == "nodsp") {
5171 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00005172 } else if (Tok.getString() == "msa") {
5173 return parseSetMsaDirective();
5174 } else if (Tok.getString() == "nomsa") {
5175 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00005176 } else if (Tok.getString() == "softfloat") {
5177 return parseSetSoftFloatDirective();
5178 } else if (Tok.getString() == "hardfloat") {
5179 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00005180 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00005181 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00005182 parseSetAssignment();
5183 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005184 }
Jack Carter07c818d2013-01-25 01:31:34 +00005185
Jack Carter0b744b32012-10-04 02:29:46 +00005186 return true;
5187}
5188
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005189/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00005190/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005191bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005192 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005193 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5194 for (;;) {
5195 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005196 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00005197 return true;
5198
5199 getParser().getStreamer().EmitValue(Value, Size);
5200
5201 if (getLexer().is(AsmToken::EndOfStatement))
5202 break;
5203
Jack Carter07c818d2013-01-25 01:31:34 +00005204 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005205 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00005206 Parser.Lex();
5207 }
5208 }
5209
5210 Parser.Lex();
5211 return false;
5212}
5213
Vladimir Medic4c299852013-11-06 11:27:05 +00005214/// parseDirectiveGpWord
5215/// ::= .gpword local_sym
5216bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005217 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00005218 const MCExpr *Value;
5219 // EmitGPRel32Value requires an expression, so we are using base class
5220 // method to evaluate the expression.
5221 if (getParser().parseExpression(Value))
5222 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00005223 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00005224
Vladimir Medice10c1122013-11-13 13:18:04 +00005225 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005226 return Error(getLexer().getLoc(),
5227 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00005228 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00005229 return false;
5230}
5231
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005232/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00005233/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005234bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005235 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005236 const MCExpr *Value;
5237 // EmitGPRel64Value requires an expression, so we are using base class
5238 // method to evaluate the expression.
5239 if (getParser().parseExpression(Value))
5240 return true;
5241 getParser().getStreamer().EmitGPRel64Value(Value);
5242
5243 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005244 return Error(getLexer().getLoc(),
5245 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00005246 Parser.Lex(); // Eat EndOfStatement token.
5247 return false;
5248}
5249
Jack Carter0cd3c192014-01-06 23:27:31 +00005250bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005251 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00005252 // Get the option token.
5253 AsmToken Tok = Parser.getTok();
5254 // At the moment only identifiers are supported.
5255 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005256 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00005257 Parser.eatToEndOfStatement();
5258 return false;
5259 }
5260
5261 StringRef Option = Tok.getIdentifier();
5262
5263 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005264 // MipsAsmParser needs to know if the current PIC mode changes.
5265 IsPicEnabled = false;
5266
Jack Carter0cd3c192014-01-06 23:27:31 +00005267 getTargetStreamer().emitDirectiveOptionPic0();
5268 Parser.Lex();
5269 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5270 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005271 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005272 Parser.eatToEndOfStatement();
5273 }
5274 return false;
5275 }
5276
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005277 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005278 // MipsAsmParser needs to know if the current PIC mode changes.
5279 IsPicEnabled = true;
5280
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005281 getTargetStreamer().emitDirectiveOptionPic2();
5282 Parser.Lex();
5283 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5284 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005285 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005286 Parser.eatToEndOfStatement();
5287 }
5288 return false;
5289 }
5290
Jack Carter0cd3c192014-01-06 23:27:31 +00005291 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00005292 Warning(Parser.getTok().getLoc(),
5293 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00005294 Parser.eatToEndOfStatement();
5295 return false;
5296}
5297
Toma Tabacu9ca50962015-04-16 09:53:47 +00005298/// parseInsnDirective
5299/// ::= .insn
5300bool MipsAsmParser::parseInsnDirective() {
5301 // If this is not the end of the statement, report an error.
5302 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5303 reportParseError("unexpected token, expected end of statement");
5304 return false;
5305 }
5306
5307 // The actual label marking happens in
5308 // MipsELFStreamer::createPendingLabelRelocs().
5309 getTargetStreamer().emitDirectiveInsn();
5310
5311 getParser().Lex(); // Eat EndOfStatement token.
5312 return false;
5313}
5314
Daniel Sanders7e527422014-07-10 13:38:23 +00005315/// parseDirectiveModule
5316/// ::= .module oddspreg
5317/// ::= .module nooddspreg
5318/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00005319/// ::= .module softfloat
5320/// ::= .module hardfloat
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005321bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005322 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005323 MCAsmLexer &Lexer = getLexer();
5324 SMLoc L = Lexer.getLoc();
5325
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00005326 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005327 // TODO : get a better message.
5328 reportParseError(".module directive must appear before any code");
5329 return false;
5330 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005331
Toma Tabacuc405c822015-01-23 10:40:19 +00005332 StringRef Option;
5333 if (Parser.parseIdentifier(Option)) {
5334 reportParseError("expected .module option identifier");
5335 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005336 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005337
Toma Tabacuc405c822015-01-23 10:40:19 +00005338 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005339 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005340
Toma Tabacu3c499582015-06-25 10:56:57 +00005341 // Synchronize the abiflags information with the FeatureBits information we
5342 // changed above.
5343 getTargetStreamer().updateABIInfo(*this);
5344
5345 // If printing assembly, use the recently updated abiflags information.
5346 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5347 // emitted at the end).
5348 getTargetStreamer().emitDirectiveModuleOddSPReg();
5349
Toma Tabacuc405c822015-01-23 10:40:19 +00005350 // If this is not the end of the statement, report an error.
5351 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5352 reportParseError("unexpected token, expected end of statement");
5353 return false;
5354 }
5355
5356 return false; // parseDirectiveModule has finished successfully.
5357 } else if (Option == "nooddspreg") {
5358 if (!isABI_O32()) {
5359 Error(L, "'.module nooddspreg' requires the O32 ABI");
5360 return false;
5361 }
5362
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005363 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005364
Toma Tabacu3c499582015-06-25 10:56:57 +00005365 // Synchronize the abiflags information with the FeatureBits information we
5366 // changed above.
5367 getTargetStreamer().updateABIInfo(*this);
5368
5369 // If printing assembly, use the recently updated abiflags information.
5370 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5371 // emitted at the end).
5372 getTargetStreamer().emitDirectiveModuleOddSPReg();
5373
Toma Tabacuc405c822015-01-23 10:40:19 +00005374 // If this is not the end of the statement, report an error.
5375 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5376 reportParseError("unexpected token, expected end of statement");
5377 return false;
5378 }
5379
5380 return false; // parseDirectiveModule has finished successfully.
5381 } else if (Option == "fp") {
5382 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00005383 } else if (Option == "softfloat") {
5384 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5385
5386 // Synchronize the ABI Flags information with the FeatureBits information we
5387 // updated above.
5388 getTargetStreamer().updateABIInfo(*this);
5389
5390 // If printing assembly, use the recently updated ABI Flags information.
5391 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5392 // emitted later).
5393 getTargetStreamer().emitDirectiveModuleSoftFloat();
5394
5395 // If this is not the end of the statement, report an error.
5396 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5397 reportParseError("unexpected token, expected end of statement");
5398 return false;
5399 }
5400
5401 return false; // parseDirectiveModule has finished successfully.
5402 } else if (Option == "hardfloat") {
5403 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5404
5405 // Synchronize the ABI Flags information with the FeatureBits information we
5406 // updated above.
5407 getTargetStreamer().updateABIInfo(*this);
5408
5409 // If printing assembly, use the recently updated ABI Flags information.
5410 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5411 // emitted later).
5412 getTargetStreamer().emitDirectiveModuleHardFloat();
5413
5414 // If this is not the end of the statement, report an error.
5415 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5416 reportParseError("unexpected token, expected end of statement");
5417 return false;
5418 }
5419
5420 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00005421 } else {
5422 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
5423 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005424}
5425
5426/// parseDirectiveModuleFP
5427/// ::= =32
5428/// ::= =xx
5429/// ::= =64
5430bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005431 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005432 MCAsmLexer &Lexer = getLexer();
5433
5434 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005435 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005436 return false;
5437 }
5438 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005439
Daniel Sanders7e527422014-07-10 13:38:23 +00005440 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005441 if (!parseFpABIValue(FpABI, ".module"))
5442 return false;
5443
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005444 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005445 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005446 return false;
5447 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005448
Toma Tabacua64e5402015-06-25 12:44:38 +00005449 // Synchronize the abiflags information with the FeatureBits information we
5450 // changed above.
5451 getTargetStreamer().updateABIInfo(*this);
5452
5453 // If printing assembly, use the recently updated abiflags information.
5454 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5455 // emitted at the end).
5456 getTargetStreamer().emitDirectiveModuleFP();
5457
Daniel Sanders7e527422014-07-10 13:38:23 +00005458 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005459 return false;
5460}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005461
Daniel Sanders7e527422014-07-10 13:38:23 +00005462bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005463 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005464 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005465 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005466 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005467
5468 if (Lexer.is(AsmToken::Identifier)) {
5469 StringRef Value = Parser.getTok().getString();
5470 Parser.Lex();
5471
5472 if (Value != "xx") {
5473 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5474 return false;
5475 }
5476
5477 if (!isABI_O32()) {
5478 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
5479 return false;
5480 }
5481
Daniel Sanders7e527422014-07-10 13:38:23 +00005482 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005483 if (ModuleLevelOptions) {
5484 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5485 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5486 } else {
5487 setFeatureBits(Mips::FeatureFPXX, "fpxx");
5488 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5489 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005490 return true;
5491 }
5492
5493 if (Lexer.is(AsmToken::Integer)) {
5494 unsigned Value = Parser.getTok().getIntVal();
5495 Parser.Lex();
5496
5497 if (Value != 32 && Value != 64) {
5498 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5499 return false;
5500 }
5501
5502 if (Value == 32) {
5503 if (!isABI_O32()) {
5504 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
5505 return false;
5506 }
5507
Daniel Sanders7e527422014-07-10 13:38:23 +00005508 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005509 if (ModuleLevelOptions) {
5510 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5511 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5512 } else {
5513 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
5514 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5515 }
Toma Tabacua64e5402015-06-25 12:44:38 +00005516 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00005517 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005518 if (ModuleLevelOptions) {
5519 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5520 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5521 } else {
5522 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
5523 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
5524 }
Toma Tabacua64e5402015-06-25 12:44:38 +00005525 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005526
Daniel Sanders7e527422014-07-10 13:38:23 +00005527 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005528 }
5529
5530 return false;
5531}
5532
Jack Carter0b744b32012-10-04 02:29:46 +00005533bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005534 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005535 StringRef IDVal = DirectiveID.getString();
5536
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005537 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005538 return parseDirectiveCpLoad(DirectiveID.getLoc());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005539 if (IDVal == ".cprestore")
5540 return parseDirectiveCpRestore(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00005541 if (IDVal == ".dword") {
5542 parseDataDirective(8, DirectiveID.getLoc());
5543 return false;
5544 }
Jack Carterd0bd6422013-04-18 00:41:53 +00005545 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005546 StringRef SymbolName;
5547
5548 if (Parser.parseIdentifier(SymbolName)) {
5549 reportParseError("expected identifier after .ent");
5550 return false;
5551 }
5552
5553 // There's an undocumented extension that allows an integer to
5554 // follow the name of the procedure which AFAICS is ignored by GAS.
5555 // Example: .ent foo,2
5556 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5557 if (getLexer().isNot(AsmToken::Comma)) {
5558 // Even though we accept this undocumented extension for compatibility
5559 // reasons, the additional integer argument does not actually change
5560 // the behaviour of the '.ent' directive, so we would like to discourage
5561 // its use. We do this by not referring to the extended version in
5562 // error messages which are not directly related to its use.
5563 reportParseError("unexpected token, expected end of statement");
5564 return false;
5565 }
5566 Parser.Lex(); // Eat the comma.
5567 const MCExpr *DummyNumber;
5568 int64_t DummyNumberVal;
5569 // If the user was explicitly trying to use the extended version,
5570 // we still give helpful extension-related error messages.
5571 if (Parser.parseExpression(DummyNumber)) {
5572 reportParseError("expected number after comma");
5573 return false;
5574 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00005575 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005576 reportParseError("expected an absolute expression after comma");
5577 return false;
5578 }
5579 }
5580
5581 // If this is not the end of the statement, report an error.
5582 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5583 reportParseError("unexpected token, expected end of statement");
5584 return false;
5585 }
5586
Jim Grosbach6f482002015-05-18 18:43:14 +00005587 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005588
5589 getTargetStreamer().emitDirectiveEnt(*Sym);
5590 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005591 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00005592 return false;
5593 }
5594
Jack Carter07c818d2013-01-25 01:31:34 +00005595 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005596 StringRef SymbolName;
5597
5598 if (Parser.parseIdentifier(SymbolName)) {
5599 reportParseError("expected identifier after .end");
5600 return false;
5601 }
5602
5603 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5604 reportParseError("unexpected token, expected end of statement");
5605 return false;
5606 }
5607
5608 if (CurrentFn == nullptr) {
5609 reportParseError(".end used without .ent");
5610 return false;
5611 }
5612
5613 if ((SymbolName != CurrentFn->getName())) {
5614 reportParseError(".end symbol does not match .ent symbol");
5615 return false;
5616 }
5617
5618 getTargetStreamer().emitDirectiveEnd(SymbolName);
5619 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005620 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00005621 return false;
5622 }
5623
Jack Carter07c818d2013-01-25 01:31:34 +00005624 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005625 // .frame $stack_reg, frame_size_in_bytes, $return_reg
5626 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005627 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005628 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5629 reportParseError("expected stack register");
5630 return false;
5631 }
5632
5633 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5634 if (!StackRegOpnd.isGPRAsmReg()) {
5635 reportParseError(StackRegOpnd.getStartLoc(),
5636 "expected general purpose register");
5637 return false;
5638 }
5639 unsigned StackReg = StackRegOpnd.getGPR32Reg();
5640
5641 if (Parser.getTok().is(AsmToken::Comma))
5642 Parser.Lex();
5643 else {
5644 reportParseError("unexpected token, expected comma");
5645 return false;
5646 }
5647
5648 // Parse the frame size.
5649 const MCExpr *FrameSize;
5650 int64_t FrameSizeVal;
5651
5652 if (Parser.parseExpression(FrameSize)) {
5653 reportParseError("expected frame size value");
5654 return false;
5655 }
5656
Jim Grosbach13760bd2015-05-30 01:25:56 +00005657 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005658 reportParseError("frame size not an absolute expression");
5659 return false;
5660 }
5661
5662 if (Parser.getTok().is(AsmToken::Comma))
5663 Parser.Lex();
5664 else {
5665 reportParseError("unexpected token, expected comma");
5666 return false;
5667 }
5668
5669 // Parse the return register.
5670 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00005671 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005672 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5673 reportParseError("expected return register");
5674 return false;
5675 }
5676
5677 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5678 if (!ReturnRegOpnd.isGPRAsmReg()) {
5679 reportParseError(ReturnRegOpnd.getStartLoc(),
5680 "expected general purpose register");
5681 return false;
5682 }
5683
5684 // If this is not the end of the statement, report an error.
5685 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5686 reportParseError("unexpected token, expected end of statement");
5687 return false;
5688 }
5689
5690 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
5691 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005692 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00005693 return false;
5694 }
5695
Jack Carter07c818d2013-01-25 01:31:34 +00005696 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00005697 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00005698 }
5699
Daniel Sandersd97a6342014-08-13 10:07:34 +00005700 if (IDVal == ".mask" || IDVal == ".fmask") {
5701 // .mask bitmask, frame_offset
5702 // bitmask: One bit for each register used.
5703 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
5704 // first register is expected to be saved.
5705 // Examples:
5706 // .mask 0x80000000, -4
5707 // .fmask 0x80000000, -4
5708 //
Jack Carterbe332172012-09-07 00:48:02 +00005709
Daniel Sandersd97a6342014-08-13 10:07:34 +00005710 // Parse the bitmask
5711 const MCExpr *BitMask;
5712 int64_t BitMaskVal;
5713
5714 if (Parser.parseExpression(BitMask)) {
5715 reportParseError("expected bitmask value");
5716 return false;
5717 }
5718
Jim Grosbach13760bd2015-05-30 01:25:56 +00005719 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005720 reportParseError("bitmask not an absolute expression");
5721 return false;
5722 }
5723
5724 if (Parser.getTok().is(AsmToken::Comma))
5725 Parser.Lex();
5726 else {
5727 reportParseError("unexpected token, expected comma");
5728 return false;
5729 }
5730
5731 // Parse the frame_offset
5732 const MCExpr *FrameOffset;
5733 int64_t FrameOffsetVal;
5734
5735 if (Parser.parseExpression(FrameOffset)) {
5736 reportParseError("expected frame offset value");
5737 return false;
5738 }
5739
Jim Grosbach13760bd2015-05-30 01:25:56 +00005740 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005741 reportParseError("frame offset not an absolute expression");
5742 return false;
5743 }
5744
5745 // If this is not the end of the statement, report an error.
5746 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5747 reportParseError("unexpected token, expected end of statement");
5748 return false;
5749 }
5750
5751 if (IDVal == ".mask")
5752 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
5753 else
5754 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00005755 return false;
5756 }
5757
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005758 if (IDVal == ".nan")
5759 return parseDirectiveNaN();
5760
Jack Carter07c818d2013-01-25 01:31:34 +00005761 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00005762 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00005763 return false;
5764 }
5765
Rafael Espindolab59fb732014-03-28 18:50:26 +00005766 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005767 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005768 return false;
5769 }
5770
Jack Carter07c818d2013-01-25 01:31:34 +00005771 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005772 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00005773 return false;
5774 }
5775
Jack Carter0cd3c192014-01-06 23:27:31 +00005776 if (IDVal == ".option")
5777 return parseDirectiveOption();
5778
5779 if (IDVal == ".abicalls") {
5780 getTargetStreamer().emitDirectiveAbiCalls();
5781 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005782 Error(Parser.getTok().getLoc(),
5783 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005784 // Clear line
5785 Parser.eatToEndOfStatement();
5786 }
5787 return false;
5788 }
5789
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005790 if (IDVal == ".cpsetup")
5791 return parseDirectiveCPSetup();
5792
Daniel Sandersf173dda2015-09-22 10:50:09 +00005793 if (IDVal == ".cpreturn")
5794 return parseDirectiveCPReturn();
5795
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005796 if (IDVal == ".module")
5797 return parseDirectiveModule();
5798
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00005799 if (IDVal == ".llvm_internal_mips_reallow_module_directive")
5800 return parseInternalDirectiveReallowModule();
5801
Toma Tabacu9ca50962015-04-16 09:53:47 +00005802 if (IDVal == ".insn")
5803 return parseInsnDirective();
5804
Rafael Espindola870c4e92012-01-11 03:56:41 +00005805 return true;
5806}
5807
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00005808bool MipsAsmParser::parseInternalDirectiveReallowModule() {
5809 // If this is not the end of the statement, report an error.
5810 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5811 reportParseError("unexpected token, expected end of statement");
5812 return false;
5813 }
5814
5815 getTargetStreamer().reallowModuleDirective();
5816
5817 getParser().Lex(); // Eat EndOfStatement token.
5818 return false;
5819}
5820
Rafael Espindola870c4e92012-01-11 03:56:41 +00005821extern "C" void LLVMInitializeMipsAsmParser() {
5822 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
5823 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
5824 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
5825 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
5826}
Jack Carterb4dbc172012-09-05 23:34:03 +00005827
5828#define GET_REGISTER_MATCHER
5829#define GET_MATCHER_IMPLEMENTATION
5830#include "MipsGenAsmMatcher.inc"