blob: 192b3444936f796f2a67d7559d02028ba3570120 [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"
Benjamin Kramerb3e8a6d2016-01-27 10:01:28 +000025#include "llvm/MC/MCParser/MCTargetAsmParser.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000026#include "llvm/MC/MCStreamer.h"
27#include "llvm/MC/MCSubtargetInfo.h"
28#include "llvm/MC/MCSymbol.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
Eric Christophera5762812015-01-26 17:33:46 +0000110 MipsABIInfo ABI;
Toma Tabacu9db22db2014-09-09 10:15:38 +0000111 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
Daniel Sandersd97a6342014-08-13 10:07:34 +0000112 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
113 // nullptr, which indicates that no function is currently
114 // selected. This usually happens after an '.end func'
115 // directive.
Toma Tabacud88d79c2015-06-23 14:39:42 +0000116 bool IsLittleEndian;
Daniel Sandersa6994442015-08-18 12:33:54 +0000117 bool IsPicEnabled;
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000118 bool IsCpRestoreSet;
119 int CpRestoreOffset;
Daniel Sandersf173dda2015-09-22 10:50:09 +0000120 unsigned CpSaveLocation;
121 /// If true, then CpSaveLocation is a register, otherwise it's an offset.
122 bool CpSaveLocationIsRegister;
Jack Carter0b744b32012-10-04 02:29:46 +0000123
Daniel Sandersef638fe2014-10-03 15:37:37 +0000124 // Print a warning along with its fix-it message at the given range.
125 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
126 SMRange Range, bool ShowColors = true);
127
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000128#define GET_ASSEMBLER_HEADER
129#include "MipsGenAsmMatcher.inc"
130
Matheus Almeida595fcab2014-06-11 15:05:56 +0000131 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
132
Chad Rosier49963552012-10-13 00:26:04 +0000133 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000134 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000135 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000136 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000137
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000138 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000139 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000140
Toma Tabacu13964452014-09-04 13:23:44 +0000141 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000142
Toma Tabacu13964452014-09-04 13:23:44 +0000143 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000144
David Blaikie960ea3f2014-06-08 16:18:35 +0000145 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
146 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000147
Craig Topper56c590a2014-04-29 07:58:02 +0000148 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000149
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000150 OperandMatchResultTy parseMemOperand(OperandVector &Operands);
151 OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000152 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000153 StringRef Identifier, SMLoc S);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000154 OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands,
155 SMLoc S);
156 OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
157 OperandMatchResultTy parseImm(OperandVector &Operands);
158 OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
159 OperandMatchResultTy parseInvNum(OperandVector &Operands);
160 OperandMatchResultTy parseLSAImm(OperandVector &Operands);
161 OperandMatchResultTy parseRegisterPair(OperandVector &Operands);
162 OperandMatchResultTy parseMovePRegPair(OperandVector &Operands);
163 OperandMatchResultTy parseRegisterList(OperandVector &Operands);
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000164
David Blaikie960ea3f2014-06-08 16:18:35 +0000165 bool searchSymbolAlias(OperandVector &Operands);
166
Toma Tabacu13964452014-09-04 13:23:44 +0000167 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000168
Daniel Sanders5bf6eab2015-10-26 23:50:00 +0000169 enum MacroExpanderResultTy {
170 MER_NotAMacro,
171 MER_Success,
172 MER_Fail,
173 };
Jack Carter30a59822012-10-04 04:03:53 +0000174
Matheus Almeida3813d572014-06-19 14:39:14 +0000175 // Expands assembly pseudo instructions.
Daniel Sanders5bf6eab2015-10-26 23:50:00 +0000176 MacroExpanderResultTy
177 tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
178 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000179
Toma Tabacu8f6603a2015-01-30 11:18:50 +0000180 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
181 SmallVectorImpl<MCInst> &Instructions);
182
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000183 bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000184 bool Is32BitImm, bool IsAddress, SMLoc IDLoc,
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000185 SmallVectorImpl<MCInst> &Instructions);
186
Toma Tabacuf712ede2015-06-17 14:31:51 +0000187 bool loadAndAddSymbolAddress(const MCExpr *SymExpr, unsigned DstReg,
188 unsigned SrcReg, bool Is32BitSym, SMLoc IDLoc,
189 SmallVectorImpl<MCInst> &Instructions);
Toma Tabacu674825c2015-06-16 12:16:24 +0000190
Toma Tabacu00e98672015-05-01 12:19:27 +0000191 bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000192 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000193
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000194 bool expandLoadAddress(unsigned DstReg, unsigned BaseReg,
195 const MCOperand &Offset, bool Is32BitAddress,
196 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000197
Jozef Kolek5cfebdd2015-01-21 12:39:30 +0000198 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
199 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000200
Jack Carter9e65aa32013-03-22 00:05:30 +0000201 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000202 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
203 bool isImmOpnd);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000204
205 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
206 SmallVectorImpl<MCInst> &Instructions);
207
Zoran Jovanoviccdb64562015-09-28 11:11:34 +0000208 bool expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
209 SmallVectorImpl<MCInst> &Instructions);
210
Toma Tabacue1e460d2015-06-11 10:36:10 +0000211 bool expandBranchImm(MCInst &Inst, SMLoc IDLoc,
212 SmallVectorImpl<MCInst> &Instructions);
213
Toma Tabacu1a108322015-06-17 13:20:24 +0000214 bool expandCondBranches(MCInst &Inst, SMLoc IDLoc,
215 SmallVectorImpl<MCInst> &Instructions);
216
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000217 bool expandDiv(MCInst &Inst, SMLoc IDLoc,
218 SmallVectorImpl<MCInst> &Instructions, const bool IsMips64,
219 const bool Signed);
220
Daniel Sanders6394ee52015-10-15 14:52:58 +0000221 bool expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
222 SmallVectorImpl<MCInst> &Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000223
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +0000224 bool expandUlw(MCInst &Inst, SMLoc IDLoc,
225 SmallVectorImpl<MCInst> &Instructions);
226
Zoran Jovanovic00f998b2015-11-19 14:15:03 +0000227 bool expandRotation(MCInst &Inst, SMLoc IDLoc,
228 SmallVectorImpl<MCInst> &Instructions);
229 bool expandRotationImm(MCInst &Inst, SMLoc IDLoc,
230 SmallVectorImpl<MCInst> &Instructions);
231 bool expandDRotation(MCInst &Inst, SMLoc IDLoc,
232 SmallVectorImpl<MCInst> &Instructions);
233 bool expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
234 SmallVectorImpl<MCInst> &Instructions);
235
Zoran Jovanovicd474ef32016-01-29 16:18:34 +0000236 bool expandAbs(MCInst &Inst, SMLoc IDLoc,
237 SmallVectorImpl<MCInst> &Instructions);
238
Toma Tabacu234482a2015-03-16 12:03:39 +0000239 void createNop(bool hasShortDelaySlot, SMLoc IDLoc,
240 SmallVectorImpl<MCInst> &Instructions);
241
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000242 void createAddu(unsigned DstReg, unsigned SrcReg, unsigned TrgReg,
Toma Tabacu0b3e9782015-06-23 14:00:54 +0000243 bool Is64Bit, SmallVectorImpl<MCInst> &Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000244
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000245 void createCpRestoreMemOp(bool IsLoad, int StackOffset, SMLoc IDLoc,
246 SmallVectorImpl<MCInst> &Instructions);
247
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000248 bool reportParseError(Twine ErrorMsg);
249 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000250
Jack Carterb5cf5902013-04-17 00:18:04 +0000251 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000252 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000253
Vladimir Medic4c299852013-11-06 11:27:05 +0000254 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000255
256 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000257 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000258 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000259 bool parseSetFeature(uint64_t Feature);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000260 bool isPicAndNotNxxAbi(); // Used by .cpload, .cprestore, and .cpsetup.
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000261 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000262 bool parseDirectiveCpRestore(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000263 bool parseDirectiveCPSetup();
Daniel Sandersf173dda2015-09-22 10:50:09 +0000264 bool parseDirectiveCPReturn();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000265 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000266 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000267 bool parseDirectiveOption();
Toma Tabacu9ca50962015-04-16 09:53:47 +0000268 bool parseInsnDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000269
270 bool parseSetAtDirective();
271 bool parseSetNoAtDirective();
272 bool parseSetMacroDirective();
273 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000274 bool parseSetMsaDirective();
275 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000276 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000277 bool parseSetReorderDirective();
278 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000279 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000280 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000281 bool parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +0000282 bool parseSetOddSPRegDirective();
283 bool parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000284 bool parseSetPopDirective();
285 bool parseSetPushDirective();
Toma Tabacu29696502015-06-02 09:48:04 +0000286 bool parseSetSoftFloatDirective();
287 bool parseSetHardFloatDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000288
Jack Carterd76b2372013-03-21 21:44:16 +0000289 bool parseSetAssignment();
290
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000291 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000292 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000293 bool parseDirectiveGpDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000294 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000295 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000296 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
297 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000298
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000299 bool parseInternalDirectiveReallowModule();
300
Jack Carterdc1e35d2012-09-06 20:00:02 +0000301 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000302
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000303 bool eatComma(StringRef ErrorStr);
304
Jack Carter1ac53222013-02-20 23:11:17 +0000305 int matchCPURegisterName(StringRef Symbol);
306
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000307 int matchHWRegsRegisterName(StringRef Symbol);
308
Jack Carter873c7242013-01-12 01:03:14 +0000309 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000310
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000311 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000312
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000313 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000314
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000315 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000316
Jack Carter5dc8ac92013-09-25 23:50:44 +0000317 int matchMSA128RegisterName(StringRef Name);
318
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000319 int matchMSA128CtrlRegisterName(StringRef Name);
320
Jack Carterd0bd6422013-04-18 00:41:53 +0000321 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000322
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000323 unsigned getGPR(int RegNo);
324
Toma Tabacu89a712b2015-04-15 10:48:56 +0000325 /// Returns the internal register number for the current AT. Also checks if
326 /// the current AT is unavailable (set to $0) and gives an error if it is.
327 /// This should be used in pseudo-instruction expansions which need AT.
328 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000329
330 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000331 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000332
333 // Helper function that checks if the value of a vector index is within the
334 // boundaries of accepted values for each RegisterKind
335 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
336 bool validateMSAIndex(int Val, int RegKind);
337
Daniel Sandersf0df2212014-08-04 12:20:00 +0000338 // Selects a new architecture by updating the FeatureBits with the necessary
339 // info including implied dependencies.
340 // Internally, it clears all the feature bits related to *any* architecture
341 // and selects the new one using the ToggleFeature functionality of the
342 // MCSubtargetInfo object that handles implied dependencies. The reason we
343 // clear all the arch related bits manually is because ToggleFeature only
344 // clears the features that imply the feature being cleared and not the
345 // features implied by the feature being cleared. This is easier to see
346 // with an example:
347 // --------------------------------------------------
348 // | Feature | Implies |
349 // | -------------------------------------------------|
350 // | FeatureMips1 | None |
351 // | FeatureMips2 | FeatureMips1 |
352 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
353 // | FeatureMips4 | FeatureMips3 |
354 // | ... | |
355 // --------------------------------------------------
356 //
357 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
358 // FeatureMipsGP64 | FeatureMips1)
359 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
360 void selectArch(StringRef ArchFeature) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000361 MCSubtargetInfo &STI = copySTI();
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000362 FeatureBitset FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000363 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
364 STI.setFeatureBits(FeatureBits);
365 setAvailableFeatures(
366 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000367 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000368 }
369
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000370 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000371 if (!(getSTI().getFeatureBits()[Feature])) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000372 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000373 setAvailableFeatures(
374 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000375 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000376 }
377 }
378
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000379 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000380 if (getSTI().getFeatureBits()[Feature]) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000381 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000382 setAvailableFeatures(
383 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000384 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000385 }
386 }
387
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000388 void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
389 setFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000390 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000391 }
392
393 void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
394 clearFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000395 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000396 }
397
Rafael Espindola870c4e92012-01-11 03:56:41 +0000398public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000399 enum MipsMatchResultTy {
Daniel Sanders52da7af2015-11-06 12:11:03 +0000400 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY,
Matheus Almeida595fcab2014-06-11 15:05:56 +0000401#define GET_OPERAND_DIAGNOSTIC_TYPES
402#include "MipsGenAsmMatcher.inc"
403#undef GET_OPERAND_DIAGNOSTIC_TYPES
Matheus Almeida595fcab2014-06-11 15:05:56 +0000404 };
405
Akira Hatanakab11ef082015-11-14 06:35:56 +0000406 MipsAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000407 const MCInstrInfo &MII, const MCTargetOptions &Options)
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000408 : MCTargetAsmParser(Options, sti),
Daniel Sanders50f17232015-09-15 16:17:27 +0000409 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
410 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000411 MCAsmParserExtension::Initialize(parser);
412
Toma Tabacu11e14a92015-04-21 11:50:52 +0000413 parser.addAliasForDirective(".asciiz", ".asciz");
414
Jack Carterb4dbc172012-09-05 23:34:03 +0000415 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000416 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000417
Toma Tabacu9db22db2014-09-09 10:15:38 +0000418 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000419 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000420 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000421
Toma Tabacu9db22db2014-09-09 10:15:38 +0000422 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000423 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000424 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000425
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000426 getTargetStreamer().updateABIInfo(*this);
427
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000428 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000429 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000430
431 CurrentFn = nullptr;
Toma Tabacud88d79c2015-06-23 14:39:42 +0000432
Daniel Sandersa6994442015-08-18 12:33:54 +0000433 IsPicEnabled =
434 (getContext().getObjectFileInfo()->getRelocM() == Reloc::PIC_);
435
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000436 IsCpRestoreSet = false;
437 CpRestoreOffset = -1;
438
Daniel Sanders50f17232015-09-15 16:17:27 +0000439 Triple TheTriple(sti.getTargetTriple());
440 if ((TheTriple.getArch() == Triple::mips) ||
441 (TheTriple.getArch() == Triple::mips64))
Toma Tabacud88d79c2015-06-23 14:39:42 +0000442 IsLittleEndian = false;
443 else
444 IsLittleEndian = true;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000445 }
446
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000447 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
448 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
449
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000450 bool isGP64bit() const {
451 return getSTI().getFeatureBits()[Mips::FeatureGP64Bit];
452 }
453 bool isFP64bit() const {
454 return getSTI().getFeatureBits()[Mips::FeatureFP64Bit];
455 }
Eric Christophera5762812015-01-26 17:33:46 +0000456 const MipsABIInfo &getABI() const { return ABI; }
457 bool isABI_N32() const { return ABI.IsN32(); }
458 bool isABI_N64() const { return ABI.IsN64(); }
459 bool isABI_O32() const { return ABI.IsO32(); }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000460 bool isABI_FPXX() const {
461 return getSTI().getFeatureBits()[Mips::FeatureFPXX];
462 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000463
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000464 bool useOddSPReg() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000465 return !(getSTI().getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000466 }
467
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000468 bool inMicroMipsMode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000469 return getSTI().getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000470 }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000471 bool hasMips1() const {
472 return getSTI().getFeatureBits()[Mips::FeatureMips1];
473 }
474 bool hasMips2() const {
475 return getSTI().getFeatureBits()[Mips::FeatureMips2];
476 }
477 bool hasMips3() const {
478 return getSTI().getFeatureBits()[Mips::FeatureMips3];
479 }
480 bool hasMips4() const {
481 return getSTI().getFeatureBits()[Mips::FeatureMips4];
482 }
483 bool hasMips5() const {
484 return getSTI().getFeatureBits()[Mips::FeatureMips5];
485 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000486 bool hasMips32() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000487 return getSTI().getFeatureBits()[Mips::FeatureMips32];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000488 }
489 bool hasMips64() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000490 return getSTI().getFeatureBits()[Mips::FeatureMips64];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000491 }
492 bool hasMips32r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000493 return getSTI().getFeatureBits()[Mips::FeatureMips32r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000494 }
495 bool hasMips64r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000496 return getSTI().getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000497 }
Daniel Sanders17793142015-02-18 16:24:50 +0000498 bool hasMips32r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000499 return (getSTI().getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000500 }
501 bool hasMips64r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000502 return (getSTI().getFeatureBits()[Mips::FeatureMips64r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000503 }
504 bool hasMips32r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000505 return (getSTI().getFeatureBits()[Mips::FeatureMips32r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000506 }
507 bool hasMips64r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000508 return (getSTI().getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000509 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000510 bool hasMips32r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000511 return getSTI().getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000512 }
513 bool hasMips64r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000514 return getSTI().getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000515 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000516
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000517 bool hasDSP() const {
518 return getSTI().getFeatureBits()[Mips::FeatureDSP];
519 }
520 bool hasDSPR2() const {
521 return getSTI().getFeatureBits()[Mips::FeatureDSPR2];
522 }
523 bool hasDSPR3() const {
524 return getSTI().getFeatureBits()[Mips::FeatureDSPR3];
525 }
526 bool hasMSA() const {
527 return getSTI().getFeatureBits()[Mips::FeatureMSA];
528 }
Kai Nackee0245392015-01-27 19:11:28 +0000529 bool hasCnMips() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000530 return (getSTI().getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000531 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000532
Daniel Sandersa6994442015-08-18 12:33:54 +0000533 bool inPicMode() {
534 return IsPicEnabled;
535 }
536
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000537 bool inMips16Mode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000538 return getSTI().getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000539 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000540
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000541 bool useTraps() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000542 return getSTI().getFeatureBits()[Mips::FeatureUseTCCInDIV];
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000543 }
544
Eric Christophere8ae3e32015-05-07 23:10:21 +0000545 bool useSoftFloat() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000546 return getSTI().getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000547 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000548
Toma Tabacud9d344b2015-04-27 14:05:04 +0000549 /// Warn if RegIndex is the same as the current AT.
550 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000551
552 void warnIfNoMacro(SMLoc Loc);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000553
554 bool isLittle() const { return IsLittleEndian; }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000555};
556}
557
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000558namespace {
559
560/// MipsOperand - Instances of this class represent a parsed Mips machine
561/// instruction.
562class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000563public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000564 /// Broad categories of register classes
565 /// The exact class is finalized by the render method.
566 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000567 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000568 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000569 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000570 RegKind_FCC = 4, /// FCC
571 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
572 RegKind_MSACtrl = 16, /// MSA control registers
573 RegKind_COP2 = 32, /// COP2
574 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
575 /// context).
576 RegKind_CCR = 128, /// CCR
577 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000578 RegKind_COP3 = 512, /// COP3
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000579 RegKind_COP0 = 1024, /// COP0
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000580 /// Potentially any (e.g. $1)
581 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
582 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000583 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
Jack Carter873c7242013-01-12 01:03:14 +0000584 };
585
586private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000587 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000588 k_Immediate, /// An immediate (possibly involving symbol references)
589 k_Memory, /// Base + Offset Memory Address
590 k_PhysRegister, /// A physical register from the Mips namespace
591 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000592 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000593 k_RegList, /// A physical register list
594 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000595 } Kind;
596
David Blaikie960ea3f2014-06-08 16:18:35 +0000597public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000598 MipsOperand(KindTy K, MipsAsmParser &Parser)
599 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
600
David Blaikie960ea3f2014-06-08 16:18:35 +0000601private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000602 /// For diagnostics, and checking the assembler temporary
603 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000604
Eric Christopher8996c5d2013-03-15 00:42:55 +0000605 struct Token {
606 const char *Data;
607 unsigned Length;
608 };
609
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000610 struct PhysRegOp {
611 unsigned Num; /// Register Number
612 };
613
614 struct RegIdxOp {
615 unsigned Index; /// Index into the register class
616 RegKind Kind; /// Bitfield of the kinds it could possibly be
617 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000618 };
619
620 struct ImmOp {
621 const MCExpr *Val;
622 };
623
624 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000625 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000626 const MCExpr *Off;
627 };
628
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000629 struct RegListOp {
630 SmallVector<unsigned, 10> *List;
631 };
632
Jack Carterb4dbc172012-09-05 23:34:03 +0000633 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000634 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000635 struct PhysRegOp PhysReg;
636 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000637 struct ImmOp Imm;
638 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000639 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000640 };
641
642 SMLoc StartLoc, EndLoc;
643
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000644 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000645 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
646 const MCRegisterInfo *RegInfo,
647 SMLoc S, SMLoc E,
648 MipsAsmParser &Parser) {
649 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000650 Op->RegIdx.Index = Index;
651 Op->RegIdx.RegInfo = RegInfo;
652 Op->RegIdx.Kind = RegKind;
653 Op->StartLoc = S;
654 Op->EndLoc = E;
655 return Op;
656 }
657
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000658public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000659 /// Coerce the register to GPR32 and return the real register for the current
660 /// target.
661 unsigned getGPR32Reg() const {
662 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000663 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000664 unsigned ClassID = Mips::GPR32RegClassID;
665 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000666 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000667
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000668 /// Coerce the register to GPR32 and return the real register for the current
669 /// target.
670 unsigned getGPRMM16Reg() const {
671 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
672 unsigned ClassID = Mips::GPR32RegClassID;
673 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
674 }
675
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000676 /// Coerce the register to GPR64 and return the real register for the current
677 /// target.
678 unsigned getGPR64Reg() const {
679 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
680 unsigned ClassID = Mips::GPR64RegClassID;
681 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000682 }
683
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000684private:
685 /// Coerce the register to AFGR64 and return the real register for the current
686 /// target.
687 unsigned getAFGR64Reg() const {
688 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
689 if (RegIdx.Index % 2 != 0)
690 AsmParser.Warning(StartLoc, "Float register should be even.");
691 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
692 .getRegister(RegIdx.Index / 2);
693 }
694
695 /// Coerce the register to FGR64 and return the real register for the current
696 /// target.
697 unsigned getFGR64Reg() const {
698 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
699 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
700 .getRegister(RegIdx.Index);
701 }
702
703 /// Coerce the register to FGR32 and return the real register for the current
704 /// target.
705 unsigned getFGR32Reg() const {
706 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
707 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
708 .getRegister(RegIdx.Index);
709 }
710
711 /// Coerce the register to FGRH32 and return the real register for the current
712 /// target.
713 unsigned getFGRH32Reg() const {
714 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
715 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
716 .getRegister(RegIdx.Index);
717 }
718
719 /// Coerce the register to FCC and return the real register for the current
720 /// target.
721 unsigned getFCCReg() const {
722 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
723 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
724 .getRegister(RegIdx.Index);
725 }
726
727 /// Coerce the register to MSA128 and return the real register for the current
728 /// target.
729 unsigned getMSA128Reg() const {
730 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
731 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
732 // identical
733 unsigned ClassID = Mips::MSA128BRegClassID;
734 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
735 }
736
737 /// Coerce the register to MSACtrl and return the real register for the
738 /// current target.
739 unsigned getMSACtrlReg() const {
740 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
741 unsigned ClassID = Mips::MSACtrlRegClassID;
742 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
743 }
744
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000745 /// Coerce the register to COP0 and return the real register for the
746 /// current target.
747 unsigned getCOP0Reg() const {
748 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");
749 unsigned ClassID = Mips::COP0RegClassID;
750 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
751 }
752
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000753 /// Coerce the register to COP2 and return the real register for the
754 /// current target.
755 unsigned getCOP2Reg() const {
756 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
757 unsigned ClassID = Mips::COP2RegClassID;
758 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
759 }
760
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000761 /// Coerce the register to COP3 and return the real register for the
762 /// current target.
763 unsigned getCOP3Reg() const {
764 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
765 unsigned ClassID = Mips::COP3RegClassID;
766 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
767 }
768
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000769 /// Coerce the register to ACC64DSP and return the real register for the
770 /// current target.
771 unsigned getACC64DSPReg() const {
772 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
773 unsigned ClassID = Mips::ACC64DSPRegClassID;
774 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
775 }
776
777 /// Coerce the register to HI32DSP and return the real register for the
778 /// current target.
779 unsigned getHI32DSPReg() const {
780 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
781 unsigned ClassID = Mips::HI32DSPRegClassID;
782 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
783 }
784
785 /// Coerce the register to LO32DSP and return the real register for the
786 /// current target.
787 unsigned getLO32DSPReg() const {
788 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
789 unsigned ClassID = Mips::LO32DSPRegClassID;
790 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
791 }
792
793 /// Coerce the register to CCR and return the real register for the
794 /// current target.
795 unsigned getCCRReg() const {
796 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
797 unsigned ClassID = Mips::CCRRegClassID;
798 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
799 }
800
801 /// Coerce the register to HWRegs and return the real register for the
802 /// current target.
803 unsigned getHWRegsReg() const {
804 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
805 unsigned ClassID = Mips::HWRegsRegClassID;
806 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
807 }
808
809public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000810 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000811 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000812 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000813 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000814 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000815 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000816 else
Jim Grosbache9119e42015-05-13 18:37:00 +0000817 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000818 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000819
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000820 void addRegOperands(MCInst &Inst, unsigned N) const {
821 llvm_unreachable("Use a custom parser instead");
822 }
823
Daniel Sanders21bce302014-04-01 12:35:23 +0000824 /// Render the operand to an MCInst as a GPR32
825 /// Asserts if the wrong number of operands are requested, or the operand
826 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000827 void addGPR32AsmRegOperands(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(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000830 }
831
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000832 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
833 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000834 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000835 }
836
Jozef Kolek1904fa22014-11-24 14:25:53 +0000837 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
838 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000839 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +0000840 }
841
Zoran Jovanovic41688672015-02-10 16:36:20 +0000842 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
843 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000844 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000845 }
846
Daniel Sanders21bce302014-04-01 12:35:23 +0000847 /// Render the operand to an MCInst as a GPR64
848 /// Asserts if the wrong number of operands are requested, or the operand
849 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000850 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
851 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000852 Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000853 }
854
855 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
856 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000857 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000858 }
859
860 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
861 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000862 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000863 }
864
865 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
866 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000867 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000868 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000869 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000870 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
871 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000872 }
873
874 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
875 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000876 Inst.addOperand(MCOperand::createReg(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000877 }
878
879 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
880 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000881 Inst.addOperand(MCOperand::createReg(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000882 }
883
884 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
885 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000886 Inst.addOperand(MCOperand::createReg(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000887 }
888
889 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
890 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000891 Inst.addOperand(MCOperand::createReg(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000892 }
893
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000894 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
895 assert(N == 1 && "Invalid number of operands!");
896 Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
897 }
898
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000899 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
900 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000901 Inst.addOperand(MCOperand::createReg(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000902 }
903
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000904 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
905 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000906 Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000907 }
908
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000909 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
910 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000911 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000912 }
913
914 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
915 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000916 Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000917 }
918
919 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
920 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000921 Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000922 }
923
924 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
925 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000926 Inst.addOperand(MCOperand::createReg(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000927 }
928
929 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
930 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000931 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000932 }
933
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +0000934 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
Daniel Sanders52da7af2015-11-06 12:11:03 +0000935 void addConstantUImmOperands(MCInst &Inst, unsigned N) const {
936 assert(N == 1 && "Invalid number of operands!");
Daniel Sandersea4f6532015-11-06 12:22:31 +0000937 uint64_t Imm = getConstantImm() - Offset;
938 Imm &= (1 << Bits) - 1;
939 Imm += Offset;
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +0000940 Imm += AdjustOffset;
Daniel Sanders52da7af2015-11-06 12:11:03 +0000941 Inst.addOperand(MCOperand::createImm(Imm));
942 }
943
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000944 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000945 assert(N == 1 && "Invalid number of operands!");
946 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000947 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000948 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000949
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000950 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000951 assert(N == 2 && "Invalid number of operands!");
952
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000953 Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
954 ? getMemBase()->getGPR64Reg()
955 : getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000956
957 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000958 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000959 }
960
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000961 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
962 assert(N == 2 && "Invalid number of operands!");
963
Jim Grosbache9119e42015-05-13 18:37:00 +0000964 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000965
966 const MCExpr *Expr = getMemOff();
967 addExpr(Inst, Expr);
968 }
969
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000970 void addRegListOperands(MCInst &Inst, unsigned N) const {
971 assert(N == 1 && "Invalid number of operands!");
972
973 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000974 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000975 }
976
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000977 void addRegPairOperands(MCInst &Inst, unsigned N) const {
978 assert(N == 2 && "Invalid number of operands!");
979 unsigned RegNo = getRegPair();
Jim Grosbache9119e42015-05-13 18:37:00 +0000980 Inst.addOperand(MCOperand::createReg(RegNo++));
981 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000982 }
983
Zoran Jovanovic41688672015-02-10 16:36:20 +0000984 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
985 assert(N == 2 && "Invalid number of operands!");
986 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000987 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000988 }
989
Craig Topper56c590a2014-04-29 07:58:02 +0000990 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000991 // As a special case until we sort out the definition of div/divu, pretend
992 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
993 if (isGPRAsmReg() && RegIdx.Index == 0)
994 return true;
995
996 return Kind == k_PhysRegister;
997 }
998 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000999 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001000 bool isConstantImm() const {
Craig Topper66059c92015-11-18 07:07:59 +00001001 return isImm() && isa<MCConstantExpr>(getImm());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001002 }
Daniel Sanders52da7af2015-11-06 12:11:03 +00001003 bool isConstantImmz() const {
1004 return isConstantImm() && getConstantImm() == 0;
1005 }
Daniel Sandersea4f6532015-11-06 12:22:31 +00001006 template <unsigned Bits, int Offset = 0> bool isConstantUImm() const {
1007 return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset);
1008 }
Zlatko Buljan252cca52015-12-18 08:59:37 +00001009 template <unsigned Bits> bool isConstantSImm() const {
1010 return isConstantImm() && isInt<Bits>(getConstantImm());
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +00001011 }
Craig Topper56c590a2014-04-29 07:58:02 +00001012 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001013 // Note: It's not possible to pretend that other operand kinds are tokens.
1014 // The matcher emitter checks tokens first.
1015 return Kind == k_Token;
1016 }
Craig Topper56c590a2014-04-29 07:58:02 +00001017 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001018 bool isConstantMemOff() const {
Craig Topper66059c92015-11-18 07:07:59 +00001019 return isMem() && isa<MCConstantExpr>(getMemOff());
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001020 }
1021 template <unsigned Bits> bool isMemWithSimmOffset() const {
Zoran Jovanovica6593ff2015-08-18 12:53:08 +00001022 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
1023 && getMemBase()->isGPRAsmReg();
1024 }
Zoran Jovanovic6e6a2c92015-09-16 09:14:35 +00001025 template <unsigned Bits> bool isMemWithSimmOffsetGPR() const {
1026 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff()) &&
1027 getMemBase()->isGPRAsmReg();
1028 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001029 bool isMemWithGRPMM16Base() const {
1030 return isMem() && getMemBase()->isMM16AsmReg();
1031 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001032 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
1033 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1034 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
1035 }
Jozef Kolek12c69822014-12-23 16:16:33 +00001036 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
1037 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1038 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1039 && (getMemBase()->getGPR32Reg() == Mips::SP);
1040 }
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001041 template <unsigned Bits, unsigned ShiftLeftAmount>
1042 bool isScaledUImm() const {
1043 return isConstantImm() &&
1044 isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm());
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00001045 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001046 bool isRegList16() const {
1047 if (!isRegList())
1048 return false;
1049
1050 int Size = RegList.List->size();
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001051 if (Size < 2 || Size > 5)
1052 return false;
1053
1054 unsigned R0 = RegList.List->front();
1055 unsigned R1 = RegList.List->back();
1056 if (!((R0 == Mips::S0 && R1 == Mips::RA) ||
1057 (R0 == Mips::S0_64 && R1 == Mips::RA_64)))
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001058 return false;
1059
1060 int PrevReg = *RegList.List->begin();
1061 for (int i = 1; i < Size - 1; i++) {
1062 int Reg = (*(RegList.List))[i];
1063 if ( Reg != PrevReg + 1)
1064 return false;
1065 PrevReg = Reg;
1066 }
1067
1068 return true;
1069 }
Vladimir Medic2b953d02013-10-01 09:48:56 +00001070 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001071 bool isLSAImm() const {
1072 if (!isConstantImm())
1073 return false;
1074 int64_t Val = getConstantImm();
1075 return 1 <= Val && Val <= 4;
1076 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001077 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001078 bool isMovePRegPair() const {
1079 if (Kind != k_RegList || RegList.List->size() != 2)
1080 return false;
1081
1082 unsigned R0 = RegList.List->front();
1083 unsigned R1 = RegList.List->back();
1084
1085 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
1086 (R0 == Mips::A1 && R1 == Mips::A3) ||
1087 (R0 == Mips::A2 && R1 == Mips::A3) ||
1088 (R0 == Mips::A0 && R1 == Mips::S5) ||
1089 (R0 == Mips::A0 && R1 == Mips::S6) ||
1090 (R0 == Mips::A0 && R1 == Mips::A1) ||
1091 (R0 == Mips::A0 && R1 == Mips::A2) ||
1092 (R0 == Mips::A0 && R1 == Mips::A3))
1093 return true;
1094
1095 return false;
1096 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001097
1098 StringRef getToken() const {
1099 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001100 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001101 }
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001102 bool isRegPair() const { return Kind == k_RegPair; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001103
Craig Topper56c590a2014-04-29 07:58:02 +00001104 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001105 // As a special case until we sort out the definition of div/divu, pretend
1106 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
1107 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1108 RegIdx.Kind & RegKind_GPR)
1109 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001110
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001111 assert(Kind == k_PhysRegister && "Invalid access!");
1112 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +00001113 }
1114
Jack Carterb4dbc172012-09-05 23:34:03 +00001115 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001116 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001117 return Imm.Val;
1118 }
1119
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001120 int64_t getConstantImm() const {
1121 const MCExpr *Val = getImm();
1122 return static_cast<const MCConstantExpr *>(Val)->getValue();
1123 }
1124
1125 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001126 assert((Kind == k_Memory) && "Invalid access!");
1127 return Mem.Base;
1128 }
1129
1130 const MCExpr *getMemOff() const {
1131 assert((Kind == k_Memory) && "Invalid access!");
1132 return Mem.Off;
1133 }
1134
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001135 int64_t getConstantMemOff() const {
1136 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1137 }
1138
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001139 const SmallVectorImpl<unsigned> &getRegList() const {
1140 assert((Kind == k_RegList) && "Invalid access!");
1141 return *(RegList.List);
1142 }
1143
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001144 unsigned getRegPair() const {
1145 assert((Kind == k_RegPair) && "Invalid access!");
1146 return RegIdx.Index;
1147 }
1148
David Blaikie960ea3f2014-06-08 16:18:35 +00001149 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1150 MipsAsmParser &Parser) {
1151 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001152 Op->Tok.Data = Str.data();
1153 Op->Tok.Length = Str.size();
1154 Op->StartLoc = S;
1155 Op->EndLoc = S;
1156 return Op;
1157 }
1158
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001159 /// Create a numeric register (e.g. $1). The exact register remains
1160 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001161 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001162 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001163 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001164 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001165 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001166 }
1167
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001168 /// Create a register that is definitely a GPR.
1169 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001170 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001171 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001172 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001173 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001174 }
1175
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001176 /// Create a register that is definitely a FGR.
1177 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001178 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001179 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001180 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001181 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
1182 }
1183
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001184 /// Create a register that is definitely a HWReg.
1185 /// This is typically only used for named registers such as $hwr_cpunum.
1186 static std::unique_ptr<MipsOperand>
1187 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
1188 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1189 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
1190 }
1191
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001192 /// Create a register that is definitely an FCC.
1193 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001194 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001195 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001196 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001197 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
1198 }
1199
1200 /// Create a register that is definitely an ACC.
1201 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001202 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001203 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001204 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001205 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
1206 }
1207
1208 /// Create a register that is definitely an MSA128.
1209 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001210 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001211 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001212 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001213 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
1214 }
1215
1216 /// Create a register that is definitely an MSACtrl.
1217 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001218 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001219 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001220 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001221 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
1222 }
1223
David Blaikie960ea3f2014-06-08 16:18:35 +00001224 static std::unique_ptr<MipsOperand>
1225 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1226 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001227 Op->Imm.Val = Val;
1228 Op->StartLoc = S;
1229 Op->EndLoc = E;
1230 return Op;
1231 }
1232
David Blaikie960ea3f2014-06-08 16:18:35 +00001233 static std::unique_ptr<MipsOperand>
1234 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1235 SMLoc E, MipsAsmParser &Parser) {
1236 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1237 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001238 Op->Mem.Off = Off;
1239 Op->StartLoc = S;
1240 Op->EndLoc = E;
1241 return Op;
1242 }
1243
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001244 static std::unique_ptr<MipsOperand>
1245 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1246 MipsAsmParser &Parser) {
1247 assert (Regs.size() > 0 && "Empty list not allowed");
1248
1249 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001250 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001251 Op->StartLoc = StartLoc;
1252 Op->EndLoc = EndLoc;
1253 return Op;
1254 }
1255
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001256 static std::unique_ptr<MipsOperand>
1257 CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1258 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
1259 Op->RegIdx.Index = RegNo;
1260 Op->StartLoc = S;
1261 Op->EndLoc = E;
1262 return Op;
1263 }
1264
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001265 bool isGPRAsmReg() const {
1266 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001267 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001268 bool isMM16AsmReg() const {
1269 if (!(isRegIdx() && RegIdx.Kind))
1270 return false;
1271 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1272 || RegIdx.Index == 16 || RegIdx.Index == 17);
1273 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001274 bool isMM16AsmRegZero() const {
1275 if (!(isRegIdx() && RegIdx.Kind))
1276 return false;
1277 return (RegIdx.Index == 0 ||
1278 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1279 RegIdx.Index == 17);
1280 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001281 bool isMM16AsmRegMoveP() const {
1282 if (!(isRegIdx() && RegIdx.Kind))
1283 return false;
1284 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1285 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1286 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001287 bool isFGRAsmReg() const {
1288 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1289 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001290 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001291 bool isHWRegsAsmReg() const {
1292 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001293 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001294 bool isCCRAsmReg() const {
1295 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001296 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001297 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001298 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1299 return false;
1300 if (!AsmParser.hasEightFccRegisters())
1301 return RegIdx.Index == 0;
1302 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001303 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001304 bool isACCAsmReg() const {
1305 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001306 }
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001307 bool isCOP0AsmReg() const {
1308 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1309 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001310 bool isCOP2AsmReg() const {
1311 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001312 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001313 bool isCOP3AsmReg() const {
1314 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1315 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001316 bool isMSA128AsmReg() const {
1317 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001318 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001319 bool isMSACtrlAsmReg() const {
1320 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001321 }
1322
Jack Carterb4dbc172012-09-05 23:34:03 +00001323 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001324 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001325 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001326 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001327
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001328 virtual ~MipsOperand() {
1329 switch (Kind) {
1330 case k_Immediate:
1331 break;
1332 case k_Memory:
1333 delete Mem.Base;
1334 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001335 case k_RegList:
1336 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001337 case k_PhysRegister:
1338 case k_RegisterIndex:
1339 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001340 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001341 break;
1342 }
1343 }
1344
Craig Topper56c590a2014-04-29 07:58:02 +00001345 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001346 switch (Kind) {
1347 case k_Immediate:
1348 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001349 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001350 OS << ">";
1351 break;
1352 case k_Memory:
1353 OS << "Mem<";
1354 Mem.Base->print(OS);
1355 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001356 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001357 OS << ">";
1358 break;
1359 case k_PhysRegister:
1360 OS << "PhysReg<" << PhysReg.Num << ">";
1361 break;
1362 case k_RegisterIndex:
1363 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1364 break;
1365 case k_Token:
1366 OS << Tok.Data;
1367 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001368 case k_RegList:
1369 OS << "RegList< ";
1370 for (auto Reg : (*RegList.List))
1371 OS << Reg << " ";
1372 OS << ">";
1373 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001374 case k_RegPair:
1375 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1376 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001377 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001378 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001379}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001380} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001381
Jack Carter9e65aa32013-03-22 00:05:30 +00001382namespace llvm {
1383extern const MCInstrDesc MipsInsts[];
1384}
1385static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1386 return MipsInsts[Opcode];
1387}
1388
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001389static bool hasShortDelaySlot(unsigned Opcode) {
1390 switch (Opcode) {
1391 case Mips::JALS_MM:
1392 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001393 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001394 case Mips::BGEZALS_MM:
1395 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001396 return true;
1397 default:
1398 return false;
1399 }
1400}
1401
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001402static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1403 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1404 return &SRExpr->getSymbol();
1405 }
1406
1407 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1408 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1409 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1410
1411 if (LHSSym)
1412 return LHSSym;
1413
1414 if (RHSSym)
1415 return RHSSym;
1416
1417 return nullptr;
1418 }
1419
1420 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1421 return getSingleMCSymbol(UExpr->getSubExpr());
1422
1423 return nullptr;
1424}
1425
1426static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1427 if (isa<MCSymbolRefExpr>(Expr))
1428 return 1;
1429
1430 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1431 return countMCSymbolRefExpr(BExpr->getLHS()) +
1432 countMCSymbolRefExpr(BExpr->getRHS());
1433
1434 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1435 return countMCSymbolRefExpr(UExpr->getSubExpr());
1436
1437 return 0;
1438}
1439
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001440namespace {
1441void emitRX(unsigned Opcode, unsigned Reg0, MCOperand Op1, SMLoc IDLoc,
1442 SmallVectorImpl<MCInst> &Instructions) {
1443 MCInst tmpInst;
1444 tmpInst.setOpcode(Opcode);
1445 tmpInst.addOperand(MCOperand::createReg(Reg0));
1446 tmpInst.addOperand(Op1);
1447 tmpInst.setLoc(IDLoc);
1448 Instructions.push_back(tmpInst);
1449}
1450
1451void emitRI(unsigned Opcode, unsigned Reg0, int32_t Imm, SMLoc IDLoc,
1452 SmallVectorImpl<MCInst> &Instructions) {
1453 emitRX(Opcode, Reg0, MCOperand::createImm(Imm), IDLoc, Instructions);
1454}
1455
1456void emitRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, SMLoc IDLoc,
1457 SmallVectorImpl<MCInst> &Instructions) {
1458 emitRX(Opcode, Reg0, MCOperand::createReg(Reg1), IDLoc, Instructions);
1459}
1460
1461void emitII(unsigned Opcode, int16_t Imm1, int16_t Imm2, SMLoc IDLoc,
1462 SmallVectorImpl<MCInst> &Instructions) {
1463 MCInst tmpInst;
1464 tmpInst.setOpcode(Opcode);
1465 tmpInst.addOperand(MCOperand::createImm(Imm1));
1466 tmpInst.addOperand(MCOperand::createImm(Imm2));
1467 tmpInst.setLoc(IDLoc);
1468 Instructions.push_back(tmpInst);
1469}
1470
1471void emitR(unsigned Opcode, unsigned Reg0, SMLoc IDLoc,
1472 SmallVectorImpl<MCInst> &Instructions) {
1473 MCInst tmpInst;
1474 tmpInst.setOpcode(Opcode);
1475 tmpInst.addOperand(MCOperand::createReg(Reg0));
1476 tmpInst.setLoc(IDLoc);
1477 Instructions.push_back(tmpInst);
1478}
1479
1480void emitRRX(unsigned Opcode, unsigned Reg0, unsigned Reg1, MCOperand Op2,
1481 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1482 MCInst tmpInst;
1483 tmpInst.setOpcode(Opcode);
1484 tmpInst.addOperand(MCOperand::createReg(Reg0));
1485 tmpInst.addOperand(MCOperand::createReg(Reg1));
1486 tmpInst.addOperand(Op2);
1487 tmpInst.setLoc(IDLoc);
1488 Instructions.push_back(tmpInst);
1489}
1490
1491void emitRRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, unsigned Reg2,
1492 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1493 emitRRX(Opcode, Reg0, Reg1, MCOperand::createReg(Reg2), IDLoc,
1494 Instructions);
1495}
1496
1497void emitRRI(unsigned Opcode, unsigned Reg0, unsigned Reg1, int16_t Imm,
1498 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1499 emitRRX(Opcode, Reg0, Reg1, MCOperand::createImm(Imm), IDLoc,
1500 Instructions);
1501}
1502
1503void emitAppropriateDSLL(unsigned DstReg, unsigned SrcReg, int16_t ShiftAmount,
1504 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1505 if (ShiftAmount >= 32) {
1506 emitRRI(Mips::DSLL32, DstReg, SrcReg, ShiftAmount - 32, IDLoc,
1507 Instructions);
1508 return;
1509 }
1510
1511 emitRRI(Mips::DSLL, DstReg, SrcReg, ShiftAmount, IDLoc, Instructions);
1512}
1513} // end anonymous namespace.
1514
Jack Carter9e65aa32013-03-22 00:05:30 +00001515bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001516 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001517 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001518 bool ExpandedJalSym = false;
Daniel Sandersa771fef2014-03-24 14:05:39 +00001519
Jack Carter9e65aa32013-03-22 00:05:30 +00001520 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001521
1522 if (MCID.isBranch() || MCID.isCall()) {
1523 const unsigned Opcode = Inst.getOpcode();
1524 MCOperand Offset;
1525
1526 switch (Opcode) {
1527 default:
1528 break;
Kai Nackee0245392015-01-27 19:11:28 +00001529 case Mips::BBIT0:
1530 case Mips::BBIT032:
1531 case Mips::BBIT1:
1532 case Mips::BBIT132:
1533 assert(hasCnMips() && "instruction only valid for octeon cpus");
1534 // Fall through
1535
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001536 case Mips::BEQ:
1537 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001538 case Mips::BEQ_MM:
1539 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001540 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001541 Offset = Inst.getOperand(2);
1542 if (!Offset.isImm())
1543 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001544 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001545 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001546 if (OffsetToAlignment(Offset.getImm(),
1547 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001548 return Error(IDLoc, "branch to misaligned address");
1549 break;
1550 case Mips::BGEZ:
1551 case Mips::BGTZ:
1552 case Mips::BLEZ:
1553 case Mips::BLTZ:
1554 case Mips::BGEZAL:
1555 case Mips::BLTZAL:
1556 case Mips::BC1F:
1557 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001558 case Mips::BGEZ_MM:
1559 case Mips::BGTZ_MM:
1560 case Mips::BLEZ_MM:
1561 case Mips::BLTZ_MM:
1562 case Mips::BGEZAL_MM:
1563 case Mips::BLTZAL_MM:
1564 case Mips::BC1F_MM:
1565 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001566 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001567 Offset = Inst.getOperand(1);
1568 if (!Offset.isImm())
1569 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001570 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001571 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001572 if (OffsetToAlignment(Offset.getImm(),
1573 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001574 return Error(IDLoc, "branch to misaligned address");
1575 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001576 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001577 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001578 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001579 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001580 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1581 Offset = Inst.getOperand(1);
1582 if (!Offset.isImm())
1583 break; // We'll deal with this situation later on when applying fixups.
Craig Topper55b1f292015-10-10 20:17:07 +00001584 if (!isInt<8>(Offset.getImm()))
Jozef Kolek9761e962015-01-12 12:03:34 +00001585 return Error(IDLoc, "branch target out of range");
1586 if (OffsetToAlignment(Offset.getImm(), 2LL))
1587 return Error(IDLoc, "branch to misaligned address");
1588 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001589 }
1590 }
1591
Daniel Sandersa84989a2014-06-16 13:25:35 +00001592 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1593 // We still accept it but it is a normal nop.
1594 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1595 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1596 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1597 "nop instruction");
1598 }
1599
Kai Nackee0245392015-01-27 19:11:28 +00001600 if (hasCnMips()) {
1601 const unsigned Opcode = Inst.getOpcode();
1602 MCOperand Opnd;
1603 int Imm;
1604
1605 switch (Opcode) {
1606 default:
1607 break;
1608
1609 case Mips::BBIT0:
1610 case Mips::BBIT032:
1611 case Mips::BBIT1:
1612 case Mips::BBIT132:
1613 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1614 // The offset is handled above
1615 Opnd = Inst.getOperand(1);
1616 if (!Opnd.isImm())
1617 return Error(IDLoc, "expected immediate operand kind");
1618 Imm = Opnd.getImm();
1619 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1620 Opcode == Mips::BBIT1 ? 63 : 31))
1621 return Error(IDLoc, "immediate operand value out of range");
1622 if (Imm > 31) {
1623 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1624 : Mips::BBIT132);
1625 Inst.getOperand(1).setImm(Imm - 32);
1626 }
1627 break;
1628
Kai Nackee0245392015-01-27 19:11:28 +00001629 case Mips::SEQi:
1630 case Mips::SNEi:
1631 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1632 Opnd = Inst.getOperand(2);
1633 if (!Opnd.isImm())
1634 return Error(IDLoc, "expected immediate operand kind");
1635 Imm = Opnd.getImm();
1636 if (!isInt<10>(Imm))
1637 return Error(IDLoc, "immediate operand value out of range");
1638 break;
1639 }
1640 }
1641
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001642 // This expansion is not in a function called by tryExpandInstruction()
1643 // because the pseudo-instruction doesn't have a distinct opcode.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001644 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
1645 inPicMode()) {
1646 warnIfNoMacro(IDLoc);
1647
1648 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
1649
1650 // We can do this expansion if there's only 1 symbol in the argument
1651 // expression.
1652 if (countMCSymbolRefExpr(JalExpr) > 1)
1653 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
1654
1655 // FIXME: This is checking the expression can be handled by the later stages
1656 // of the assembler. We ought to leave it to those later stages but
1657 // we can't do that until we stop evaluateRelocExpr() rewriting the
1658 // expressions into non-equivalent forms.
1659 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
1660
1661 // FIXME: Add support for label+offset operands (currently causes an error).
1662 // FIXME: Add support for forward-declared local symbols.
1663 // FIXME: Add expansion for when the LargeGOT option is enabled.
1664 if (JalSym->isInSection() || JalSym->isTemporary()) {
1665 if (isABI_O32()) {
1666 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001667 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001668 // R_(MICRO)MIPS_GOT16 label
1669 // addiu $25, $25, 0
1670 // R_(MICRO)MIPS_LO16 label
1671 // jalr $25
1672 const MCExpr *Got16RelocExpr = evaluateRelocExpr(JalExpr, "got");
1673 const MCExpr *Lo16RelocExpr = evaluateRelocExpr(JalExpr, "lo");
1674
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001675 emitRRX(Mips::LW, Mips::T9, Mips::GP,
1676 MCOperand::createExpr(Got16RelocExpr), IDLoc, Instructions);
1677 emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
1678 MCOperand::createExpr(Lo16RelocExpr), IDLoc, Instructions);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001679 } else if (isABI_N32() || isABI_N64()) {
1680 // If it's a local symbol and the N32/N64 ABIs are being used,
1681 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001682 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001683 // R_(MICRO)MIPS_GOT_DISP label
1684 // jalr $25
1685 const MCExpr *GotDispRelocExpr = evaluateRelocExpr(JalExpr, "got_disp");
1686
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001687 emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
1688 MCOperand::createExpr(GotDispRelocExpr), IDLoc, Instructions);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001689 }
1690 } else {
Daniel Sandersb7002032015-11-20 13:16:35 +00001691 // If it's an external/weak symbol, we expand to:
1692 // lw/ld $25, 0($gp)
1693 // R_(MICRO)MIPS_CALL16 label
1694 // jalr $25
1695 const MCExpr *Call16RelocExpr = evaluateRelocExpr(JalExpr, "call16");
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001696
Daniel Sandersb7002032015-11-20 13:16:35 +00001697 emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
1698 MCOperand::createExpr(Call16RelocExpr), IDLoc, Instructions);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001699 }
1700
1701 MCInst JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001702 if (IsCpRestoreSet && inMicroMipsMode())
1703 JalrInst.setOpcode(Mips::JALRS_MM);
1704 else
1705 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001706 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
1707 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
1708
1709 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
1710 // This relocation is supposed to be an optimization hint for the linker
1711 // and is not necessary for correctness.
1712
1713 Inst = JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001714 ExpandedJalSym = true;
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001715 }
1716
Jack Carter9e65aa32013-03-22 00:05:30 +00001717 if (MCID.mayLoad() || MCID.mayStore()) {
1718 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001719 // reference or immediate we may have to expand instructions.
1720 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001721 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001722 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1723 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001724 MCOperand &Op = Inst.getOperand(i);
1725 if (Op.isImm()) {
1726 int MemOffset = Op.getImm();
1727 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001728 // Offset can't exceed 16bit value.
1729 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001730 return false;
1731 }
1732 } else if (Op.isExpr()) {
1733 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001734 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001735 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001736 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001737 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001738 // Expand symbol.
1739 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001740 return false;
1741 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001742 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001743 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001744 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001745 }
1746 }
1747 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001748 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001749 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001750
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001751 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001752 if (MCID.mayLoad()) {
1753 // Try to create 16-bit GP relative load instruction.
1754 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1755 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1756 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1757 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1758 MCOperand &Op = Inst.getOperand(i);
1759 if (Op.isImm()) {
1760 int MemOffset = Op.getImm();
1761 MCOperand &DstReg = Inst.getOperand(0);
1762 MCOperand &BaseReg = Inst.getOperand(1);
Craig Topper55b1f292015-10-10 20:17:07 +00001763 if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&
Jozef Koleke10a02e2015-01-28 17:27:26 +00001764 getContext().getRegisterInfo()->getRegClass(
1765 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00001766 (BaseReg.getReg() == Mips::GP ||
1767 BaseReg.getReg() == Mips::GP_64)) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001768
1769 emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
1770 IDLoc, Instructions);
Jozef Koleke10a02e2015-01-28 17:27:26 +00001771 return false;
1772 }
1773 }
1774 }
1775 } // for
1776 } // if load
1777
1778 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1779
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001780 MCOperand Opnd;
1781 int Imm;
1782
1783 switch (Inst.getOpcode()) {
1784 default:
1785 break;
1786 case Mips::ADDIUS5_MM:
1787 Opnd = Inst.getOperand(2);
1788 if (!Opnd.isImm())
1789 return Error(IDLoc, "expected immediate operand kind");
1790 Imm = Opnd.getImm();
1791 if (Imm < -8 || Imm > 7)
1792 return Error(IDLoc, "immediate operand value out of range");
1793 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001794 case Mips::ADDIUSP_MM:
1795 Opnd = Inst.getOperand(0);
1796 if (!Opnd.isImm())
1797 return Error(IDLoc, "expected immediate operand kind");
1798 Imm = Opnd.getImm();
1799 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1800 Imm % 4 != 0)
1801 return Error(IDLoc, "immediate operand value out of range");
1802 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001803 case Mips::SLL16_MM:
1804 case Mips::SRL16_MM:
1805 Opnd = Inst.getOperand(2);
1806 if (!Opnd.isImm())
1807 return Error(IDLoc, "expected immediate operand kind");
1808 Imm = Opnd.getImm();
1809 if (Imm < 1 || Imm > 8)
1810 return Error(IDLoc, "immediate operand value out of range");
1811 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001812 case Mips::LI16_MM:
1813 Opnd = Inst.getOperand(1);
1814 if (!Opnd.isImm())
1815 return Error(IDLoc, "expected immediate operand kind");
1816 Imm = Opnd.getImm();
1817 if (Imm < -1 || Imm > 126)
1818 return Error(IDLoc, "immediate operand value out of range");
1819 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001820 case Mips::ADDIUR2_MM:
1821 Opnd = Inst.getOperand(2);
1822 if (!Opnd.isImm())
1823 return Error(IDLoc, "expected immediate operand kind");
1824 Imm = Opnd.getImm();
1825 if (!(Imm == 1 || Imm == -1 ||
1826 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1827 return Error(IDLoc, "immediate operand value out of range");
1828 break;
Zoran Jovanovic42b84442014-10-23 11:13:59 +00001829 case Mips::ADDIUR1SP_MM:
1830 Opnd = Inst.getOperand(1);
1831 if (!Opnd.isImm())
1832 return Error(IDLoc, "expected immediate operand kind");
1833 Imm = Opnd.getImm();
1834 if (OffsetToAlignment(Imm, 4LL))
1835 return Error(IDLoc, "misaligned immediate operand value");
1836 if (Imm < 0 || Imm > 255)
1837 return Error(IDLoc, "immediate operand value out of range");
1838 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001839 case Mips::ANDI16_MM:
1840 Opnd = Inst.getOperand(2);
1841 if (!Opnd.isImm())
1842 return Error(IDLoc, "expected immediate operand kind");
1843 Imm = Opnd.getImm();
1844 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1845 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1846 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1847 return Error(IDLoc, "immediate operand value out of range");
1848 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001849 case Mips::LBU16_MM:
1850 Opnd = Inst.getOperand(2);
1851 if (!Opnd.isImm())
1852 return Error(IDLoc, "expected immediate operand kind");
1853 Imm = Opnd.getImm();
1854 if (Imm < -1 || Imm > 14)
1855 return Error(IDLoc, "immediate operand value out of range");
1856 break;
Zoran Jovanovic7ba636c2015-09-17 10:14:09 +00001857 case Mips::TEQ_MM:
1858 case Mips::TGE_MM:
1859 case Mips::TGEU_MM:
1860 case Mips::TLT_MM:
1861 case Mips::TLTU_MM:
1862 case Mips::TNE_MM:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001863 case Mips::SB16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001864 case Mips::SB16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001865 Opnd = Inst.getOperand(2);
1866 if (!Opnd.isImm())
1867 return Error(IDLoc, "expected immediate operand kind");
1868 Imm = Opnd.getImm();
1869 if (Imm < 0 || Imm > 15)
1870 return Error(IDLoc, "immediate operand value out of range");
1871 break;
1872 case Mips::LHU16_MM:
1873 case Mips::SH16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001874 case Mips::SH16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001875 Opnd = Inst.getOperand(2);
1876 if (!Opnd.isImm())
1877 return Error(IDLoc, "expected immediate operand kind");
1878 Imm = Opnd.getImm();
1879 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1880 return Error(IDLoc, "immediate operand value out of range");
1881 break;
1882 case Mips::LW16_MM:
1883 case Mips::SW16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001884 case Mips::SW16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001885 Opnd = Inst.getOperand(2);
1886 if (!Opnd.isImm())
1887 return Error(IDLoc, "expected immediate operand kind");
1888 Imm = Opnd.getImm();
1889 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1890 return Error(IDLoc, "immediate operand value out of range");
1891 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001892 case Mips::ADDIUPC_MM:
1893 MCOperand Opnd = Inst.getOperand(1);
1894 if (!Opnd.isImm())
1895 return Error(IDLoc, "expected immediate operand kind");
1896 int Imm = Opnd.getImm();
Craig Topper55b1f292015-10-10 20:17:07 +00001897 if ((Imm % 4 != 0) || !isInt<25>(Imm))
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001898 return Error(IDLoc, "immediate operand value out of range");
1899 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001900 }
1901 }
1902
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001903 MacroExpanderResultTy ExpandResult =
1904 tryExpandInstruction(Inst, IDLoc, Instructions);
1905 switch (ExpandResult) {
1906 case MER_NotAMacro:
Jack Carter9e65aa32013-03-22 00:05:30 +00001907 Instructions.push_back(Inst);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001908 break;
1909 case MER_Success:
1910 break;
1911 case MER_Fail:
1912 return true;
1913 }
Jack Carter9e65aa32013-03-22 00:05:30 +00001914
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001915 // If this instruction has a delay slot and .set reorder is active,
1916 // emit a NOP after it.
1917 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
1918 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1919
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001920 if ((Inst.getOpcode() == Mips::JalOneReg ||
1921 Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
1922 isPicAndNotNxxAbi()) {
1923 if (IsCpRestoreSet) {
1924 // We need a NOP between the JALR and the LW:
1925 // If .set reorder has been used, we've already emitted a NOP.
1926 // If .set noreorder has been used, we need to emit a NOP at this point.
1927 if (!AssemblerOptions.back()->isReorder())
1928 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1929
1930 // Load the $gp from the stack.
1931 SmallVector<MCInst, 3> LoadInsts;
1932 createCpRestoreMemOp(true /*IsLoad*/, CpRestoreOffset /*StackOffset*/,
1933 IDLoc, LoadInsts);
1934
1935 for (const MCInst &Inst : LoadInsts)
1936 Instructions.push_back(Inst);
1937
1938 } else
1939 Warning(IDLoc, "no .cprestore used in PIC mode");
1940 }
1941
Jack Carter9e65aa32013-03-22 00:05:30 +00001942 return false;
1943}
1944
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001945MipsAsmParser::MacroExpanderResultTy
1946MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
1947 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001948 switch (Inst.getOpcode()) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001949 default:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001950 return MER_NotAMacro;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001951 case Mips::LoadImm32:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001952 return expandLoadImm(Inst, true, IDLoc, Instructions) ? MER_Fail
1953 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001954 case Mips::LoadImm64:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001955 return expandLoadImm(Inst, false, IDLoc, Instructions) ? MER_Fail
1956 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001957 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001958 case Mips::LoadAddrImm64:
1959 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1960 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
1961 "expected immediate operand kind");
1962
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001963 return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,
1964 Inst.getOperand(1),
1965 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,
1966 Instructions)
1967 ? MER_Fail
1968 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001969 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001970 case Mips::LoadAddrReg64:
1971 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1972 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1973 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
1974 "expected immediate operand kind");
1975
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001976 return expandLoadAddress(Inst.getOperand(0).getReg(),
1977 Inst.getOperand(1).getReg(), Inst.getOperand(2),
1978 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,
1979 Instructions)
1980 ? MER_Fail
1981 : MER_Success;
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001982 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001983 case Mips::B_MMR6_Pseudo:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001984 return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions) ? MER_Fail
1985 : MER_Success;
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001986 case Mips::SWM_MM:
1987 case Mips::LWM_MM:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001988 return expandLoadStoreMultiple(Inst, IDLoc, Instructions) ? MER_Fail
1989 : MER_Success;
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001990 case Mips::JalOneReg:
1991 case Mips::JalTwoReg:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001992 return expandJalWithRegs(Inst, IDLoc, Instructions) ? MER_Fail
1993 : MER_Success;
Toma Tabacue1e460d2015-06-11 10:36:10 +00001994 case Mips::BneImm:
1995 case Mips::BeqImm:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001996 return expandBranchImm(Inst, IDLoc, Instructions) ? MER_Fail : MER_Success;
Toma Tabacu1a108322015-06-17 13:20:24 +00001997 case Mips::BLT:
1998 case Mips::BLE:
1999 case Mips::BGE:
2000 case Mips::BGT:
2001 case Mips::BLTU:
2002 case Mips::BLEU:
2003 case Mips::BGEU:
2004 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002005 case Mips::BLTL:
2006 case Mips::BLEL:
2007 case Mips::BGEL:
2008 case Mips::BGTL:
2009 case Mips::BLTUL:
2010 case Mips::BLEUL:
2011 case Mips::BGEUL:
2012 case Mips::BGTUL:
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002013 case Mips::BLTImmMacro:
2014 case Mips::BLEImmMacro:
2015 case Mips::BGEImmMacro:
2016 case Mips::BGTImmMacro:
2017 case Mips::BLTUImmMacro:
2018 case Mips::BLEUImmMacro:
2019 case Mips::BGEUImmMacro:
2020 case Mips::BGTUImmMacro:
2021 case Mips::BLTLImmMacro:
2022 case Mips::BLELImmMacro:
2023 case Mips::BGELImmMacro:
2024 case Mips::BGTLImmMacro:
2025 case Mips::BLTULImmMacro:
2026 case Mips::BLEULImmMacro:
2027 case Mips::BGEULImmMacro:
2028 case Mips::BGTULImmMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002029 return expandCondBranches(Inst, IDLoc, Instructions) ? MER_Fail
2030 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002031 case Mips::SDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002032 return expandDiv(Inst, IDLoc, Instructions, false, true) ? MER_Fail
2033 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002034 case Mips::DSDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002035 return expandDiv(Inst, IDLoc, Instructions, true, true) ? MER_Fail
2036 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002037 case Mips::UDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002038 return expandDiv(Inst, IDLoc, Instructions, false, false) ? MER_Fail
2039 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002040 case Mips::DUDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002041 return expandDiv(Inst, IDLoc, Instructions, true, false) ? MER_Fail
2042 : MER_Success;
Daniel Sanders6394ee52015-10-15 14:52:58 +00002043 case Mips::Ulh:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002044 return expandUlh(Inst, true, IDLoc, Instructions) ? MER_Fail : MER_Success;
Toma Tabacud88d79c2015-06-23 14:39:42 +00002045 case Mips::Ulhu:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002046 return expandUlh(Inst, false, IDLoc, Instructions) ? MER_Fail : MER_Success;
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00002047 case Mips::Ulw:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002048 return expandUlw(Inst, IDLoc, Instructions) ? MER_Fail : MER_Success;
2049 case Mips::NORImm:
2050 return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail
2051 : MER_Success;
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002052 case Mips::ADDi:
2053 case Mips::ADDiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002054 case Mips::SLTi:
2055 case Mips::SLTiu:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002056 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2057 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2058 int64_t ImmValue = Inst.getOperand(2).getImm();
2059 if (isInt<16>(ImmValue))
2060 return MER_NotAMacro;
2061 return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail
2062 : MER_Success;
2063 }
2064 return MER_NotAMacro;
2065 case Mips::ANDi:
2066 case Mips::ORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002067 case Mips::XORi:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002068 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2069 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2070 int64_t ImmValue = Inst.getOperand(2).getImm();
2071 if (isUInt<16>(ImmValue))
2072 return MER_NotAMacro;
2073 return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail
2074 : MER_Success;
2075 }
2076 return MER_NotAMacro;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002077 case Mips::ROL:
2078 case Mips::ROR:
2079 return expandRotation(Inst, IDLoc, Instructions) ? MER_Fail
2080 : MER_Success;
2081 case Mips::ROLImm:
2082 case Mips::RORImm:
2083 return expandRotationImm(Inst, IDLoc, Instructions) ? MER_Fail
2084 : MER_Success;
2085 case Mips::DROL:
2086 case Mips::DROR:
2087 return expandDRotation(Inst, IDLoc, Instructions) ? MER_Fail
2088 : MER_Success;
2089 case Mips::DROLImm:
2090 case Mips::DRORImm:
2091 return expandDRotationImm(Inst, IDLoc, Instructions) ? MER_Fail
2092 : MER_Success;
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00002093 case Mips::ABSMacro:
2094 return expandAbs(Inst, IDLoc, Instructions) ? MER_Fail
2095 : MER_Success;
Jack Carterd0bd6422013-04-18 00:41:53 +00002096 }
Jack Carter30a59822012-10-04 04:03:53 +00002097}
Jack Carter92995f12012-10-06 00:53:28 +00002098
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002099bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
2100 SmallVectorImpl<MCInst> &Instructions) {
2101 // Create a JALR instruction which is going to replace the pseudo-JAL.
2102 MCInst JalrInst;
2103 JalrInst.setLoc(IDLoc);
2104 const MCOperand FirstRegOp = Inst.getOperand(0);
2105 const unsigned Opcode = Inst.getOpcode();
2106
2107 if (Opcode == Mips::JalOneReg) {
2108 // jal $rs => jalr $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002109 if (IsCpRestoreSet && inMicroMipsMode()) {
2110 JalrInst.setOpcode(Mips::JALRS16_MM);
2111 JalrInst.addOperand(FirstRegOp);
2112 } else if (inMicroMipsMode()) {
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002113 JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002114 JalrInst.addOperand(FirstRegOp);
2115 } else {
2116 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002117 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002118 JalrInst.addOperand(FirstRegOp);
2119 }
2120 } else if (Opcode == Mips::JalTwoReg) {
2121 // jal $rd, $rs => jalr $rd, $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002122 if (IsCpRestoreSet && inMicroMipsMode())
2123 JalrInst.setOpcode(Mips::JALRS_MM);
2124 else
2125 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002126 JalrInst.addOperand(FirstRegOp);
2127 const MCOperand SecondRegOp = Inst.getOperand(1);
2128 JalrInst.addOperand(SecondRegOp);
2129 }
2130 Instructions.push_back(JalrInst);
2131
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002132 // If .set reorder is active and branch instruction has a delay slot,
2133 // emit a NOP after it.
2134 const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
2135 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) {
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002136 createNop(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc, Instructions);
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002137 }
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002138
2139 return false;
2140}
2141
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002142/// Can the value be represented by a unsigned N-bit value and a shift left?
Benjamin Kramer039b1042015-10-28 13:54:36 +00002143template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002144 unsigned BitNum = findFirstSet(x);
2145
2146 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2147}
2148
2149/// Load (or add) an immediate into a register.
2150///
2151/// @param ImmValue The immediate to load.
2152/// @param DstReg The register that will hold the immediate.
2153/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2154/// for a simple initialization.
2155/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2156/// @param IsAddress True if the immediate represents an address. False if it
2157/// is an integer.
2158/// @param IDLoc Location of the immediate in the source file.
2159/// @param Instructions The instructions emitted by this expansion.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002160bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002161 unsigned SrcReg, bool Is32BitImm,
2162 bool IsAddress, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00002163 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu00e98672015-05-01 12:19:27 +00002164 if (!Is32BitImm && !isGP64bit()) {
2165 Error(IDLoc, "instruction requires a 64-bit architecture");
2166 return true;
2167 }
2168
Daniel Sanders03f9c012015-07-14 12:24:22 +00002169 if (Is32BitImm) {
2170 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2171 // Sign extend up to 64-bit so that the predicates match the hardware
2172 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2173 // true.
2174 ImmValue = SignExtend64<32>(ImmValue);
2175 } else {
2176 Error(IDLoc, "instruction requires a 32-bit immediate");
2177 return true;
2178 }
2179 }
2180
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002181 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2182 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2183
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002184 bool UseSrcReg = false;
2185 if (SrcReg != Mips::NoRegister)
2186 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002187
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002188 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002189 if (UseSrcReg &&
2190 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002191 // At this point we need AT to perform the expansions and we exit if it is
2192 // not available.
2193 unsigned ATReg = getATReg(IDLoc);
2194 if (!ATReg)
2195 return true;
2196 TmpReg = ATReg;
2197 }
2198
Daniel Sanders03f9c012015-07-14 12:24:22 +00002199 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002200 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002201 SrcReg = ZeroReg;
2202
2203 // This doesn't quite follow the usual ABI expectations for N32 but matches
2204 // traditional assembler behaviour. N32 would normally use addiu for both
2205 // integers and addresses.
2206 if (IsAddress && !Is32BitImm) {
2207 emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
2208 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002209 }
2210
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002211 emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
2212 return false;
2213 }
2214
2215 if (isUInt<16>(ImmValue)) {
2216 unsigned TmpReg = DstReg;
2217 if (SrcReg == DstReg) {
2218 TmpReg = getATReg(IDLoc);
2219 if (!TmpReg)
2220 return true;
2221 }
2222
2223 emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002224 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002225 emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2226 return false;
2227 }
2228
2229 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002230 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002231
Toma Tabacu79588102015-04-29 10:19:56 +00002232 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2233 uint16_t Bits15To0 = ImmValue & 0xffff;
2234
Toma Tabacua3d056f2015-05-15 09:42:11 +00002235 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002236 // Traditional behaviour seems to special case this particular value. It's
2237 // not clear why other masks are handled differently.
2238 if (ImmValue == 0xffffffff) {
Daniel Sandersf1ae3672015-08-18 09:55:57 +00002239 emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, Instructions);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002240 emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, Instructions);
2241 if (UseSrcReg)
2242 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2243 return false;
2244 }
2245
2246 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002247 // upper 32 bits.
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002248 emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002249 emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, Instructions);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002250 if (Bits15To0)
2251 emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
2252 if (UseSrcReg)
2253 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2254 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002255 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002256
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002257 emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, Instructions);
2258 if (Bits15To0)
2259 emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002260 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002261 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2262 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002263 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002264
2265 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2266 if (Is32BitImm) {
2267 Error(IDLoc, "instruction requires a 32-bit immediate");
2268 return true;
2269 }
2270
2271 // Traditionally, these immediates are shifted as little as possible and as
2272 // such we align the most significant bit to bit 15 of our temporary.
2273 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2274 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2275 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2276 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
2277 emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, Instructions);
2278 emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, Instructions);
2279
2280 if (UseSrcReg)
2281 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2282
2283 return false;
2284 }
2285
2286 warnIfNoMacro(IDLoc);
2287
2288 // The remaining case is packed with a sequence of dsll and ori with zeros
2289 // being omitted and any neighbouring dsll's being coalesced.
2290 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2291
2292 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2293 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
2294 IDLoc, Instructions))
2295 return false;
2296
2297 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2298 // skip it and defer the shift to the next chunk.
2299 unsigned ShiftCarriedForwards = 16;
2300 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2301 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2302
2303 if (ImmChunk != 0) {
2304 emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
2305 Instructions);
2306 emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, Instructions);
2307 ShiftCarriedForwards = 0;
2308 }
2309
2310 ShiftCarriedForwards += 16;
2311 }
2312 ShiftCarriedForwards -= 16;
2313
2314 // Finish any remaining shifts left by trailing zeros.
2315 if (ShiftCarriedForwards)
2316 emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
2317 Instructions);
2318
2319 if (UseSrcReg)
2320 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2321
Matheus Almeida3813d572014-06-19 14:39:14 +00002322 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002323}
Jack Carter92995f12012-10-06 00:53:28 +00002324
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002325bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
2326 SmallVectorImpl<MCInst> &Instructions) {
2327 const MCOperand &ImmOp = Inst.getOperand(1);
2328 assert(ImmOp.isImm() && "expected immediate operand kind");
2329 const MCOperand &DstRegOp = Inst.getOperand(0);
2330 assert(DstRegOp.isReg() && "expected register operand kind");
2331
2332 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002333 Is32BitImm, false, IDLoc, Instructions))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002334 return true;
2335
2336 return false;
2337}
2338
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002339bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2340 const MCOperand &Offset,
2341 bool Is32BitAddress, SMLoc IDLoc,
2342 SmallVectorImpl<MCInst> &Instructions) {
2343 // la can't produce a usable address when addresses are 64-bit.
2344 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2345 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2346 // We currently can't do this because we depend on the equality
2347 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2348 Error(IDLoc, "la used to load 64-bit address");
2349 // Continue as if we had 'dla' instead.
2350 Is32BitAddress = false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002351 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002352
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002353 // dla requires 64-bit addresses.
Scott Egerton24557012016-01-21 15:11:01 +00002354 if (!Is32BitAddress && !hasMips3()) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002355 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002356 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002357 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002358
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002359 if (!Offset.isImm())
2360 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
2361 Is32BitAddress, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002362
Scott Egerton24557012016-01-21 15:11:01 +00002363 if (!ABI.ArePtrs64bit()) {
2364 // Continue as if we had 'la' whether we had 'la' or 'dla'.
2365 Is32BitAddress = true;
2366 }
2367
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002368 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
2369 IDLoc, Instructions);
Jack Carter543fdf82012-10-09 23:29:45 +00002370}
2371
Toma Tabacuf712ede2015-06-17 14:31:51 +00002372bool MipsAsmParser::loadAndAddSymbolAddress(
2373 const MCExpr *SymExpr, unsigned DstReg, unsigned SrcReg, bool Is32BitSym,
2374 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002375 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002376
Daniel Sandersd5a89412015-10-05 13:19:29 +00002377 const MCExpr *Symbol = cast<MCExpr>(SymExpr);
2378 const MipsMCExpr *HiExpr = MipsMCExpr::create(
2379 MCSymbolRefExpr::VK_Mips_ABS_HI, Symbol, getContext());
2380 const MipsMCExpr *LoExpr = MipsMCExpr::create(
2381 MCSymbolRefExpr::VK_Mips_ABS_LO, Symbol, getContext());
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002382
Toma Tabacufb9d1252015-06-22 12:08:39 +00002383 bool UseSrcReg = SrcReg != Mips::NoRegister;
2384
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002385 // This is the 64-bit symbol address expansion.
2386 if (ABI.ArePtrs64bit() && isGP64bit()) {
2387 // We always need AT for the 64-bit expansion.
2388 // If it is not available we exit.
2389 unsigned ATReg = getATReg(IDLoc);
2390 if (!ATReg)
2391 return true;
2392
Daniel Sandersd5a89412015-10-05 13:19:29 +00002393 const MipsMCExpr *HighestExpr = MipsMCExpr::create(
2394 MCSymbolRefExpr::VK_Mips_HIGHEST, Symbol, getContext());
2395 const MipsMCExpr *HigherExpr = MipsMCExpr::create(
2396 MCSymbolRefExpr::VK_Mips_HIGHER, Symbol, getContext());
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002397
Scott Egerton24557012016-01-21 15:11:01 +00002398 if (UseSrcReg &&
2399 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2400 SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002401 // If $rs is the same as $rd:
2402 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
2403 // daddiu $at, $at, %higher(sym)
2404 // dsll $at, $at, 16
2405 // daddiu $at, $at, %hi(sym)
2406 // dsll $at, $at, 16
2407 // daddiu $at, $at, %lo(sym)
2408 // daddu $rd, $at, $rd
2409 emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
2410 Instructions);
2411 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HigherExpr),
2412 IDLoc, Instructions);
2413 emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
2414 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
2415 Instructions);
2416 emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
2417 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
2418 Instructions);
2419 emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, Instructions);
2420
2421 return false;
2422 }
2423
2424 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2425 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
2426 // lui $at, %hi(sym)
2427 // daddiu $rd, $rd, %higher(sym)
2428 // daddiu $at, $at, %lo(sym)
2429 // dsll32 $rd, $rd, 0
2430 // daddu $rd, $rd, $at
2431 // (daddu $rd, $rd, $rs)
2432 emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
2433 Instructions);
2434 emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
2435 Instructions);
2436 emitRRX(Mips::DADDiu, DstReg, DstReg, MCOperand::createExpr(HigherExpr),
2437 IDLoc, Instructions);
2438 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
2439 Instructions);
2440 emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, Instructions);
2441 emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, Instructions);
2442 if (UseSrcReg)
2443 emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, Instructions);
2444
2445 return false;
2446 }
2447
2448 // And now, the 32-bit symbol address expansion:
2449 // If $rs is the same as $rd:
2450 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
2451 // ori $at, $at, %lo(sym)
2452 // addu $rd, $at, $rd
2453 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2454 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
2455 // ori $rd, $rd, %lo(sym)
2456 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00002457 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002458 if (UseSrcReg &&
2459 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002460 // If $rs is the same as $rd, we need to use AT.
2461 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00002462 unsigned ATReg = getATReg(IDLoc);
2463 if (!ATReg)
2464 return true;
2465 TmpReg = ATReg;
2466 }
2467
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002468 emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, Instructions);
2469 emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr), IDLoc,
2470 Instructions);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002471
Toma Tabacufb9d1252015-06-22 12:08:39 +00002472 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002473 emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2474 else
Scott Egerton24557012016-01-21 15:11:01 +00002475 assert(
2476 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, TmpReg));
Toma Tabacuf712ede2015-06-17 14:31:51 +00002477
Toma Tabacu674825c2015-06-16 12:16:24 +00002478 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002479}
2480
NAKAMURA Takumi2bbc90c2015-01-23 01:02:07 +00002481bool MipsAsmParser::expandUncondBranchMMPseudo(
2482 MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00002483 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
2484 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002485
2486 MCOperand Offset = Inst.getOperand(0);
2487 if (Offset.isExpr()) {
2488 Inst.clear();
2489 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002490 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2491 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2492 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002493 } else {
2494 assert(Offset.isImm() && "expected immediate operand kind");
Craig Topper55b1f292015-10-10 20:17:07 +00002495 if (isInt<11>(Offset.getImm())) {
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002496 // If offset fits into 11 bits then this instruction becomes microMIPS
2497 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00002498 if (inMicroMipsMode())
2499 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002500 } else {
Craig Topper55b1f292015-10-10 20:17:07 +00002501 if (!isInt<17>(Offset.getImm()))
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002502 Error(IDLoc, "branch target out of range");
2503 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
2504 Error(IDLoc, "branch to misaligned address");
2505 Inst.clear();
2506 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002507 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2508 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2509 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002510 }
2511 }
2512 Instructions.push_back(Inst);
2513
Zoran Jovanovicada70912015-09-07 11:56:37 +00002514 // If .set reorder is active and branch instruction has a delay slot,
2515 // emit a NOP after it.
2516 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
2517 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Toma Tabacu234482a2015-03-16 12:03:39 +00002518 createNop(true, IDLoc, Instructions);
2519
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002520 return false;
2521}
2522
Toma Tabacue1e460d2015-06-11 10:36:10 +00002523bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc,
2524 SmallVectorImpl<MCInst> &Instructions) {
2525 const MCOperand &DstRegOp = Inst.getOperand(0);
2526 assert(DstRegOp.isReg() && "expected register operand kind");
2527
2528 const MCOperand &ImmOp = Inst.getOperand(1);
2529 assert(ImmOp.isImm() && "expected immediate operand kind");
2530
2531 const MCOperand &MemOffsetOp = Inst.getOperand(2);
2532 assert(MemOffsetOp.isImm() && "expected immediate operand kind");
2533
2534 unsigned OpCode = 0;
2535 switch(Inst.getOpcode()) {
2536 case Mips::BneImm:
2537 OpCode = Mips::BNE;
2538 break;
2539 case Mips::BeqImm:
2540 OpCode = Mips::BEQ;
2541 break;
2542 default:
2543 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
2544 break;
2545 }
2546
2547 int64_t ImmValue = ImmOp.getImm();
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002548 if (ImmValue == 0)
2549 emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
2550 Instructions);
2551 else {
Toma Tabacue1e460d2015-06-11 10:36:10 +00002552 warnIfNoMacro(IDLoc);
2553
2554 unsigned ATReg = getATReg(IDLoc);
2555 if (!ATReg)
2556 return true;
2557
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002558 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
2559 IDLoc, Instructions))
Toma Tabacue1e460d2015-06-11 10:36:10 +00002560 return true;
2561
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002562 emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, Instructions);
Toma Tabacue1e460d2015-06-11 10:36:10 +00002563 }
2564 return false;
2565}
2566
Jack Carter9e65aa32013-03-22 00:05:30 +00002567void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00002568 SmallVectorImpl<MCInst> &Instructions,
2569 bool isLoad, bool isImmOpnd) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002570 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00002571 const MCExpr *ExprOffset;
2572 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00002573 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002574 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2575 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002576 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002577 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2578 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002579 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00002580 if (isImmOpnd) {
2581 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
2582 ImmOffset = Inst.getOperand(2).getImm();
2583 LoOffset = ImmOffset & 0x0000ffff;
2584 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00002585 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00002586 if (LoOffset & 0x8000)
2587 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00002588 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00002589 ExprOffset = Inst.getOperand(2).getExpr();
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002590 // These are some of the types of expansions we perform here:
2591 // 1) lw $8, sym => lui $8, %hi(sym)
2592 // lw $8, %lo(sym)($8)
2593 // 2) lw $8, offset($9) => lui $8, %hi(offset)
2594 // add $8, $8, $9
2595 // lw $8, %lo(offset)($9)
2596 // 3) lw $8, offset($8) => lui $at, %hi(offset)
2597 // add $at, $at, $8
2598 // lw $8, %lo(offset)($at)
2599 // 4) sw $8, sym => lui $at, %hi(sym)
2600 // sw $8, %lo(sym)($at)
2601 // 5) sw $8, offset($8) => lui $at, %hi(offset)
2602 // add $at, $at, $8
2603 // sw $8, %lo(offset)($at)
2604 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
2605 // ldc1 $f0, %lo(sym)($at)
2606 //
2607 // For load instructions we can use the destination register as a temporary
2608 // if base and dst are different (examples 1 and 2) and if the base register
2609 // is general purpose otherwise we must use $at (example 6) and error if it's
2610 // not available. For stores we must use $at (examples 4 and 5) because we
2611 // must not clobber the source register setting up the offset.
2612 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
2613 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
2614 unsigned RegClassIDOp0 =
2615 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
2616 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
2617 (RegClassIDOp0 == Mips::GPR64RegClassID);
2618 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00002619 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002620 else {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002621 // At this point we need AT to perform the expansions and we exit if it is
2622 // not available.
Toma Tabacu89a712b2015-04-15 10:48:56 +00002623 TmpRegNum = getATReg(IDLoc);
2624 if (!TmpRegNum)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002625 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002626 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002627
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002628 emitRX(Mips::LUi, TmpRegNum,
2629 isImmOpnd ? MCOperand::createImm(HiOffset)
2630 : MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "hi")),
2631 IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00002632 // Add temp register to base.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002633 if (BaseRegNum != Mips::ZERO)
2634 emitRRR(Mips::ADDu, TmpRegNum, TmpRegNum, BaseRegNum, IDLoc, Instructions);
Alp Tokercb402912014-01-24 17:20:08 +00002635 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00002636 // of offset and new base.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002637 emitRRX(Inst.getOpcode(), RegOpNum, TmpRegNum,
2638 isImmOpnd
2639 ? MCOperand::createImm(LoOffset)
2640 : MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "lo")),
2641 IDLoc, Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +00002642}
2643
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002644bool
2645MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2646 SmallVectorImpl<MCInst> &Instructions) {
2647 unsigned OpNum = Inst.getNumOperands();
2648 unsigned Opcode = Inst.getOpcode();
2649 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2650
2651 assert (Inst.getOperand(OpNum - 1).isImm() &&
2652 Inst.getOperand(OpNum - 2).isReg() &&
2653 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2654
2655 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2656 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002657 (Inst.getOperand(OpNum - 2).getReg() == Mips::SP ||
2658 Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) &&
2659 (Inst.getOperand(OpNum - 3).getReg() == Mips::RA ||
2660 Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002661 // It can be implemented as SWM16 or LWM16 instruction.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002662 if (inMicroMipsMode() && hasMips32r6())
2663 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6;
2664 else
2665 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2666 }
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002667
2668 Inst.setOpcode(NewOpcode);
2669 Instructions.push_back(Inst);
2670 return false;
2671}
2672
Toma Tabacu1a108322015-06-17 13:20:24 +00002673bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
2674 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002675 bool EmittedNoMacroWarning = false;
Toma Tabacu1a108322015-06-17 13:20:24 +00002676 unsigned PseudoOpcode = Inst.getOpcode();
2677 unsigned SrcReg = Inst.getOperand(0).getReg();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002678 const MCOperand &TrgOp = Inst.getOperand(1);
Toma Tabacu1a108322015-06-17 13:20:24 +00002679 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
2680
2681 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002682 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00002683
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002684 unsigned TrgReg;
2685 if (TrgOp.isReg())
2686 TrgReg = TrgOp.getReg();
2687 else if (TrgOp.isImm()) {
2688 warnIfNoMacro(IDLoc);
2689 EmittedNoMacroWarning = true;
2690
2691 TrgReg = getATReg(IDLoc);
2692 if (!TrgReg)
2693 return true;
2694
2695 switch(PseudoOpcode) {
2696 default:
2697 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2698 case Mips::BLTImmMacro:
2699 PseudoOpcode = Mips::BLT;
2700 break;
2701 case Mips::BLEImmMacro:
2702 PseudoOpcode = Mips::BLE;
2703 break;
2704 case Mips::BGEImmMacro:
2705 PseudoOpcode = Mips::BGE;
2706 break;
2707 case Mips::BGTImmMacro:
2708 PseudoOpcode = Mips::BGT;
2709 break;
2710 case Mips::BLTUImmMacro:
2711 PseudoOpcode = Mips::BLTU;
2712 break;
2713 case Mips::BLEUImmMacro:
2714 PseudoOpcode = Mips::BLEU;
2715 break;
2716 case Mips::BGEUImmMacro:
2717 PseudoOpcode = Mips::BGEU;
2718 break;
2719 case Mips::BGTUImmMacro:
2720 PseudoOpcode = Mips::BGTU;
2721 break;
2722 case Mips::BLTLImmMacro:
2723 PseudoOpcode = Mips::BLTL;
2724 break;
2725 case Mips::BLELImmMacro:
2726 PseudoOpcode = Mips::BLEL;
2727 break;
2728 case Mips::BGELImmMacro:
2729 PseudoOpcode = Mips::BGEL;
2730 break;
2731 case Mips::BGTLImmMacro:
2732 PseudoOpcode = Mips::BGTL;
2733 break;
2734 case Mips::BLTULImmMacro:
2735 PseudoOpcode = Mips::BLTUL;
2736 break;
2737 case Mips::BLEULImmMacro:
2738 PseudoOpcode = Mips::BLEUL;
2739 break;
2740 case Mips::BGEULImmMacro:
2741 PseudoOpcode = Mips::BGEUL;
2742 break;
2743 case Mips::BGTULImmMacro:
2744 PseudoOpcode = Mips::BGTUL;
2745 break;
2746 }
2747
2748 if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
2749 false, IDLoc, Instructions))
2750 return true;
2751 }
2752
Toma Tabacu1a108322015-06-17 13:20:24 +00002753 switch (PseudoOpcode) {
2754 case Mips::BLT:
2755 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002756 case Mips::BLTL:
2757 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002758 AcceptsEquality = false;
2759 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002760 IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
2761 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002762 ZeroSrcOpcode = Mips::BGTZ;
2763 ZeroTrgOpcode = Mips::BLTZ;
2764 break;
2765 case Mips::BLE:
2766 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002767 case Mips::BLEL:
2768 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002769 AcceptsEquality = true;
2770 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002771 IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
2772 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002773 ZeroSrcOpcode = Mips::BGEZ;
2774 ZeroTrgOpcode = Mips::BLEZ;
2775 break;
2776 case Mips::BGE:
2777 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002778 case Mips::BGEL:
2779 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002780 AcceptsEquality = true;
2781 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002782 IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
2783 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002784 ZeroSrcOpcode = Mips::BLEZ;
2785 ZeroTrgOpcode = Mips::BGEZ;
2786 break;
2787 case Mips::BGT:
2788 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002789 case Mips::BGTL:
2790 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002791 AcceptsEquality = false;
2792 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002793 IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
2794 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002795 ZeroSrcOpcode = Mips::BLTZ;
2796 ZeroTrgOpcode = Mips::BGTZ;
2797 break;
2798 default:
2799 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2800 }
2801
Toma Tabacu1a108322015-06-17 13:20:24 +00002802 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
2803 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
2804 if (IsSrcRegZero && IsTrgRegZero) {
2805 // FIXME: All of these Opcode-specific if's are needed for compatibility
2806 // with GAS' behaviour. However, they may not generate the most efficient
2807 // code in some circumstances.
2808 if (PseudoOpcode == Mips::BLT) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002809 emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2810 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002811 return false;
2812 }
2813 if (PseudoOpcode == Mips::BLE) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002814 emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2815 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002816 Warning(IDLoc, "branch is always taken");
2817 return false;
2818 }
2819 if (PseudoOpcode == Mips::BGE) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002820 emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2821 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002822 Warning(IDLoc, "branch is always taken");
2823 return false;
2824 }
2825 if (PseudoOpcode == Mips::BGT) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002826 emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2827 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002828 return false;
2829 }
2830 if (PseudoOpcode == Mips::BGTU) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002831 emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
2832 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002833 return false;
2834 }
2835 if (AcceptsEquality) {
2836 // If both registers are $0 and the pseudo-branch accepts equality, it
2837 // will always be taken, so we emit an unconditional branch.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002838 emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
2839 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002840 Warning(IDLoc, "branch is always taken");
2841 return false;
2842 }
2843 // If both registers are $0 and the pseudo-branch does not accept
2844 // equality, it will never be taken, so we don't have to emit anything.
2845 return false;
2846 }
2847 if (IsSrcRegZero || IsTrgRegZero) {
2848 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
2849 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
2850 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
2851 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
2852 // the pseudo-branch will never be taken, so we don't emit anything.
2853 // This only applies to unsigned pseudo-branches.
2854 return false;
2855 }
2856 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
2857 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
2858 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
2859 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
2860 // the pseudo-branch will always be taken, so we emit an unconditional
2861 // branch.
2862 // This only applies to unsigned pseudo-branches.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002863 emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
2864 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002865 Warning(IDLoc, "branch is always taken");
2866 return false;
2867 }
2868 if (IsUnsigned) {
2869 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
2870 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
2871 // the pseudo-branch will be taken only when the non-zero register is
2872 // different from 0, so we emit a BNEZ.
2873 //
2874 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
2875 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
2876 // the pseudo-branch will be taken only when the non-zero register is
2877 // equal to 0, so we emit a BEQZ.
2878 //
2879 // Because only BLEU and BGEU branch on equality, we can use the
2880 // AcceptsEquality variable to decide when to emit the BEQZ.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002881 emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
2882 IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
2883 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002884 return false;
2885 }
2886 // If we have a signed pseudo-branch and one of the registers is $0,
2887 // we can use an appropriate compare-to-zero branch. We select which one
2888 // to use in the switch statement above.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002889 emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
2890 IsSrcRegZero ? TrgReg : SrcReg, MCOperand::createExpr(OffsetExpr),
2891 IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002892 return false;
2893 }
2894
2895 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
2896 // expansions. If it is not available, we return.
2897 unsigned ATRegNum = getATReg(IDLoc);
2898 if (!ATRegNum)
2899 return true;
2900
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002901 if (!EmittedNoMacroWarning)
2902 warnIfNoMacro(IDLoc);
Toma Tabacu1a108322015-06-17 13:20:24 +00002903
2904 // SLT fits well with 2 of our 4 pseudo-branches:
2905 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
2906 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
2907 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
2908 // This is accomplished by using a BNEZ with the result of the SLT.
2909 //
2910 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
2911 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
2912 // Because only BGE and BLE branch on equality, we can use the
2913 // AcceptsEquality variable to decide when to emit the BEQZ.
2914 // Note that the order of the SLT arguments doesn't change between
2915 // opposites.
2916 //
2917 // The same applies to the unsigned variants, except that SLTu is used
2918 // instead of SLT.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002919 emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
2920 ReverseOrderSLT ? TrgReg : SrcReg, ReverseOrderSLT ? SrcReg : TrgReg,
2921 IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002922
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002923 emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
2924 : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
2925 ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2926 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002927 return false;
2928}
2929
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002930bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc,
2931 SmallVectorImpl<MCInst> &Instructions,
2932 const bool IsMips64, const bool Signed) {
2933 if (hasMips32r6()) {
2934 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
2935 return false;
2936 }
2937
2938 warnIfNoMacro(IDLoc);
2939
2940 const MCOperand &RsRegOp = Inst.getOperand(0);
2941 assert(RsRegOp.isReg() && "expected register operand kind");
2942 unsigned RsReg = RsRegOp.getReg();
2943
2944 const MCOperand &RtRegOp = Inst.getOperand(1);
2945 assert(RtRegOp.isReg() && "expected register operand kind");
2946 unsigned RtReg = RtRegOp.getReg();
2947 unsigned DivOp;
2948 unsigned ZeroReg;
2949
2950 if (IsMips64) {
2951 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
2952 ZeroReg = Mips::ZERO_64;
2953 } else {
2954 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
2955 ZeroReg = Mips::ZERO;
2956 }
2957
2958 bool UseTraps = useTraps();
2959
2960 if (RsReg == Mips::ZERO || RsReg == Mips::ZERO_64) {
2961 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)
2962 Warning(IDLoc, "dividing zero by zero");
2963 if (IsMips64) {
2964 if (Signed && (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)) {
2965 if (UseTraps) {
2966 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2967 return false;
2968 }
2969
2970 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2971 return false;
2972 }
2973 } else {
2974 emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
2975 return false;
2976 }
2977 }
2978
2979 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
2980 Warning(IDLoc, "division by zero");
2981 if (Signed) {
2982 if (UseTraps) {
2983 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2984 return false;
2985 }
2986
2987 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2988 return false;
2989 }
2990 }
2991
2992 // FIXME: The values for these two BranchTarget variables may be different in
2993 // micromips. These magic numbers need to be removed.
2994 unsigned BranchTargetNoTraps;
2995 unsigned BranchTarget;
2996
2997 if (UseTraps) {
2998 BranchTarget = IsMips64 ? 12 : 8;
2999 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
3000 } else {
3001 BranchTarget = IsMips64 ? 20 : 16;
3002 BranchTargetNoTraps = 8;
3003 // Branch to the li instruction.
3004 emitRRI(Mips::BNE, RtReg, ZeroReg, BranchTargetNoTraps, IDLoc,
3005 Instructions);
3006 }
3007
3008 emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
3009
3010 if (!UseTraps)
3011 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
3012
3013 if (!Signed) {
3014 emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
3015 return false;
3016 }
3017
3018 unsigned ATReg = getATReg(IDLoc);
3019 if (!ATReg)
3020 return true;
3021
3022 emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, Instructions);
3023 if (IsMips64) {
3024 // Branch to the mflo instruction.
3025 emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
3026 emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, Instructions);
3027 emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, Instructions);
3028 } else {
3029 // Branch to the mflo instruction.
3030 emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
3031 emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, Instructions);
3032 }
3033
3034 if (UseTraps)
3035 emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, Instructions);
3036 else {
3037 // Branch to the mflo instruction.
3038 emitRRI(Mips::BNE, RsReg, ATReg, BranchTargetNoTraps, IDLoc, Instructions);
3039 emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, Instructions);
3040 emitII(Mips::BREAK, 0x6, 0, IDLoc, Instructions);
3041 }
3042 emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
3043 return false;
3044}
3045
Daniel Sanders6394ee52015-10-15 14:52:58 +00003046bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
3047 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacud88d79c2015-06-23 14:39:42 +00003048 if (hasMips32r6() || hasMips64r6()) {
3049 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3050 return false;
3051 }
3052
3053 warnIfNoMacro(IDLoc);
3054
3055 const MCOperand &DstRegOp = Inst.getOperand(0);
3056 assert(DstRegOp.isReg() && "expected register operand kind");
3057
3058 const MCOperand &SrcRegOp = Inst.getOperand(1);
3059 assert(SrcRegOp.isReg() && "expected register operand kind");
3060
3061 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3062 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3063
3064 unsigned DstReg = DstRegOp.getReg();
3065 unsigned SrcReg = SrcRegOp.getReg();
3066 int64_t OffsetValue = OffsetImmOp.getImm();
3067
3068 // NOTE: We always need AT for ULHU, as it is always used as the source
3069 // register for one of the LBu's.
3070 unsigned ATReg = getATReg(IDLoc);
3071 if (!ATReg)
3072 return true;
3073
3074 // When the value of offset+1 does not fit in 16 bits, we have to load the
3075 // offset in AT, (D)ADDu the original source register (if there was one), and
3076 // then use AT as the source register for the 2 generated LBu's.
3077 bool LoadedOffsetInAT = false;
3078 if (!isInt<16>(OffsetValue + 1) || !isInt<16>(OffsetValue)) {
3079 LoadedOffsetInAT = true;
3080
3081 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003082 true, IDLoc, Instructions))
Toma Tabacud88d79c2015-06-23 14:39:42 +00003083 return true;
3084
3085 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3086 // because it will make our output more similar to GAS'. For example,
3087 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3088 // instead of just an "ori $1, $9, 32768".
3089 // NOTE: If there is no source register specified in the ULHU, the parser
3090 // will interpret it as $0.
3091 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
3092 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
3093 }
3094
3095 unsigned FirstLbuDstReg = LoadedOffsetInAT ? DstReg : ATReg;
3096 unsigned SecondLbuDstReg = LoadedOffsetInAT ? ATReg : DstReg;
3097 unsigned LbuSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3098
3099 int64_t FirstLbuOffset = 0, SecondLbuOffset = 0;
3100 if (isLittle()) {
3101 FirstLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3102 SecondLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3103 } else {
3104 FirstLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3105 SecondLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3106 }
3107
3108 unsigned SllReg = LoadedOffsetInAT ? DstReg : ATReg;
3109
Daniel Sanders6394ee52015-10-15 14:52:58 +00003110 emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
3111 FirstLbuOffset, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003112
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003113 emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondLbuOffset, IDLoc,
3114 Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003115
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003116 emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003117
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003118 emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003119
3120 return false;
3121}
3122
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003123bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc,
3124 SmallVectorImpl<MCInst> &Instructions) {
3125 if (hasMips32r6() || hasMips64r6()) {
3126 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3127 return false;
3128 }
3129
3130 const MCOperand &DstRegOp = Inst.getOperand(0);
3131 assert(DstRegOp.isReg() && "expected register operand kind");
3132
3133 const MCOperand &SrcRegOp = Inst.getOperand(1);
3134 assert(SrcRegOp.isReg() && "expected register operand kind");
3135
3136 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3137 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3138
3139 unsigned SrcReg = SrcRegOp.getReg();
3140 int64_t OffsetValue = OffsetImmOp.getImm();
3141 unsigned ATReg = 0;
3142
3143 // When the value of offset+3 does not fit in 16 bits, we have to load the
3144 // offset in AT, (D)ADDu the original source register (if there was one), and
3145 // then use AT as the source register for the generated LWL and LWR.
3146 bool LoadedOffsetInAT = false;
3147 if (!isInt<16>(OffsetValue + 3) || !isInt<16>(OffsetValue)) {
3148 ATReg = getATReg(IDLoc);
3149 if (!ATReg)
3150 return true;
3151 LoadedOffsetInAT = true;
3152
3153 warnIfNoMacro(IDLoc);
3154
3155 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003156 true, IDLoc, Instructions))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003157 return true;
3158
3159 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3160 // because it will make our output more similar to GAS'. For example,
3161 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3162 // instead of just an "ori $1, $9, 32768".
3163 // NOTE: If there is no source register specified in the ULW, the parser
3164 // will interpret it as $0.
3165 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
3166 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
3167 }
3168
3169 unsigned FinalSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3170 int64_t LeftLoadOffset = 0, RightLoadOffset = 0;
3171 if (isLittle()) {
3172 LeftLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3173 RightLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3174 } else {
3175 LeftLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3176 RightLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3177 }
3178
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003179 emitRRI(Mips::LWL, DstRegOp.getReg(), FinalSrcReg, LeftLoadOffset, IDLoc,
3180 Instructions);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003181
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003182 emitRRI(Mips::LWR, DstRegOp.getReg(), FinalSrcReg, RightLoadOffset, IDLoc,
3183 Instructions);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003184
3185 return false;
3186}
3187
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003188bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
3189 SmallVectorImpl<MCInst> &Instructions) {
3190
3191 assert (Inst.getNumOperands() == 3 && "Invalid operand count");
3192 assert (Inst.getOperand(0).isReg() &&
3193 Inst.getOperand(1).isReg() &&
3194 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
3195
3196 unsigned ATReg = Mips::NoRegister;
3197 unsigned FinalDstReg = Mips::NoRegister;
3198 unsigned DstReg = Inst.getOperand(0).getReg();
3199 unsigned SrcReg = Inst.getOperand(1).getReg();
3200 int64_t ImmValue = Inst.getOperand(2).getImm();
3201
3202 bool Is32Bit = isInt<32>(ImmValue) || isUInt<32>(ImmValue);
3203
3204 unsigned FinalOpcode = Inst.getOpcode();
3205
3206 if (DstReg == SrcReg) {
3207 ATReg = getATReg(Inst.getLoc());
3208 if (!ATReg)
3209 return true;
3210 FinalDstReg = DstReg;
3211 DstReg = ATReg;
3212 }
3213
3214 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Instructions)) {
3215 switch (FinalOpcode) {
3216 default:
3217 llvm_unreachable("unimplemented expansion");
3218 case (Mips::ADDi):
3219 FinalOpcode = Mips::ADD;
3220 break;
3221 case (Mips::ADDiu):
3222 FinalOpcode = Mips::ADDu;
3223 break;
3224 case (Mips::ANDi):
3225 FinalOpcode = Mips::AND;
3226 break;
3227 case (Mips::NORImm):
3228 FinalOpcode = Mips::NOR;
3229 break;
3230 case (Mips::ORi):
3231 FinalOpcode = Mips::OR;
3232 break;
3233 case (Mips::SLTi):
3234 FinalOpcode = Mips::SLT;
3235 break;
3236 case (Mips::SLTiu):
3237 FinalOpcode = Mips::SLTu;
3238 break;
3239 case (Mips::XORi):
3240 FinalOpcode = Mips::XOR;
3241 break;
3242 }
3243
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003244 if (FinalDstReg == Mips::NoRegister)
3245 emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, Instructions);
3246 else
3247 emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc,
3248 Instructions);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003249 return false;
3250 }
3251 return true;
3252}
3253
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003254bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc,
3255 SmallVectorImpl<MCInst> &Instructions) {
3256 unsigned ATReg = Mips::NoRegister;
3257 unsigned DReg = Inst.getOperand(0).getReg();
3258 unsigned SReg = Inst.getOperand(1).getReg();
3259 unsigned TReg = Inst.getOperand(2).getReg();
3260 unsigned TmpReg = DReg;
3261
3262 unsigned FirstShift = Mips::NOP;
3263 unsigned SecondShift = Mips::NOP;
3264
3265 if (hasMips32r2()) {
3266
3267 if (DReg == SReg) {
3268 TmpReg = getATReg(Inst.getLoc());
3269 if (!TmpReg)
3270 return true;
3271 }
3272
3273 if (Inst.getOpcode() == Mips::ROL) {
3274 emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions);
3275 emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), Instructions);
3276 return false;
3277 }
3278
3279 if (Inst.getOpcode() == Mips::ROR) {
3280 emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), Instructions);
3281 return false;
3282 }
3283
3284 return true;
3285 }
3286
3287 if (hasMips32()) {
3288
3289 switch (Inst.getOpcode()) {
3290 default:
3291 llvm_unreachable("unexpected instruction opcode");
3292 case Mips::ROL:
3293 FirstShift = Mips::SRLV;
3294 SecondShift = Mips::SLLV;
3295 break;
3296 case Mips::ROR:
3297 FirstShift = Mips::SLLV;
3298 SecondShift = Mips::SRLV;
3299 break;
3300 }
3301
3302 ATReg = getATReg(Inst.getLoc());
3303 if (!ATReg)
3304 return true;
3305
3306 emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions);
3307 emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), Instructions);
3308 emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), Instructions);
3309 emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions);
3310
3311 return false;
3312 }
3313
3314 return true;
3315}
3316
3317bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
3318 SmallVectorImpl<MCInst> &Instructions) {
3319
3320 unsigned ATReg = Mips::NoRegister;
3321 unsigned DReg = Inst.getOperand(0).getReg();
3322 unsigned SReg = Inst.getOperand(1).getReg();
3323 int64_t ImmValue = Inst.getOperand(2).getImm();
3324
3325 unsigned FirstShift = Mips::NOP;
3326 unsigned SecondShift = Mips::NOP;
3327
3328 if (hasMips32r2()) {
3329
3330 if (Inst.getOpcode() == Mips::ROLImm) {
3331 uint64_t MaxShift = 32;
3332 uint64_t ShiftValue = ImmValue;
3333 if (ImmValue != 0)
3334 ShiftValue = MaxShift - ImmValue;
3335 emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), Instructions);
3336 return false;
3337 }
3338
3339 if (Inst.getOpcode() == Mips::RORImm) {
3340 emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), Instructions);
3341 return false;
3342 }
3343
3344 return true;
3345 }
3346
3347 if (hasMips32()) {
3348
3349 if (ImmValue == 0) {
3350 emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), Instructions);
3351 return false;
3352 }
3353
3354 switch (Inst.getOpcode()) {
3355 default:
3356 llvm_unreachable("unexpected instruction opcode");
3357 case Mips::ROLImm:
3358 FirstShift = Mips::SLL;
3359 SecondShift = Mips::SRL;
3360 break;
3361 case Mips::RORImm:
3362 FirstShift = Mips::SRL;
3363 SecondShift = Mips::SLL;
3364 break;
3365 }
3366
3367 ATReg = getATReg(Inst.getLoc());
3368 if (!ATReg)
3369 return true;
3370
3371 emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), Instructions);
3372 emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), Instructions);
3373 emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions);
3374
3375 return false;
3376 }
3377
3378 return true;
3379}
3380
3381bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc,
3382 SmallVectorImpl<MCInst> &Instructions) {
3383
3384 unsigned ATReg = Mips::NoRegister;
3385 unsigned DReg = Inst.getOperand(0).getReg();
3386 unsigned SReg = Inst.getOperand(1).getReg();
3387 unsigned TReg = Inst.getOperand(2).getReg();
3388 unsigned TmpReg = DReg;
3389
3390 unsigned FirstShift = Mips::NOP;
3391 unsigned SecondShift = Mips::NOP;
3392
3393 if (hasMips64r2()) {
3394
3395 if (TmpReg == SReg) {
3396 TmpReg = getATReg(Inst.getLoc());
3397 if (!TmpReg)
3398 return true;
3399 }
3400
3401 if (Inst.getOpcode() == Mips::DROL) {
3402 emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions);
3403 emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), Instructions);
3404 return false;
3405 }
3406
3407 if (Inst.getOpcode() == Mips::DROR) {
3408 emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), Instructions);
3409 return false;
3410 }
3411
3412 return true;
3413 }
3414
3415 if (hasMips64()) {
3416
3417 switch (Inst.getOpcode()) {
3418 default:
3419 llvm_unreachable("unexpected instruction opcode");
3420 case Mips::DROL:
3421 FirstShift = Mips::DSRLV;
3422 SecondShift = Mips::DSLLV;
3423 break;
3424 case Mips::DROR:
3425 FirstShift = Mips::DSLLV;
3426 SecondShift = Mips::DSRLV;
3427 break;
3428 }
3429
3430 ATReg = getATReg(Inst.getLoc());
3431 if (!ATReg)
3432 return true;
3433
3434 emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions);
3435 emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), Instructions);
3436 emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), Instructions);
3437 emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions);
3438
3439 return false;
3440 }
3441
3442 return true;
3443}
3444
3445bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
3446 SmallVectorImpl<MCInst> &Instructions) {
3447
3448 unsigned ATReg = Mips::NoRegister;
3449 unsigned DReg = Inst.getOperand(0).getReg();
3450 unsigned SReg = Inst.getOperand(1).getReg();
3451 int64_t ImmValue = Inst.getOperand(2).getImm() % 64;
3452
3453 unsigned FirstShift = Mips::NOP;
3454 unsigned SecondShift = Mips::NOP;
3455
3456 MCInst TmpInst;
3457
3458 if (hasMips64r2()) {
3459
3460 unsigned FinalOpcode = Mips::NOP;
3461 if (ImmValue == 0)
3462 FinalOpcode = Mips::DROTR;
3463 else if (ImmValue % 32 == 0)
3464 FinalOpcode = Mips::DROTR32;
3465 else if ((ImmValue >= 1) && (ImmValue <= 32)) {
3466 if (Inst.getOpcode() == Mips::DROLImm)
3467 FinalOpcode = Mips::DROTR32;
3468 else
3469 FinalOpcode = Mips::DROTR;
3470 } else if (ImmValue >= 33) {
3471 if (Inst.getOpcode() == Mips::DROLImm)
3472 FinalOpcode = Mips::DROTR;
3473 else
3474 FinalOpcode = Mips::DROTR32;
3475 }
3476
3477 uint64_t ShiftValue = ImmValue % 32;
3478 if (Inst.getOpcode() == Mips::DROLImm)
3479 ShiftValue = (32 - ImmValue % 32) % 32;
3480
3481 emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), Instructions);
3482
3483 return false;
3484 }
3485
3486 if (hasMips64()) {
3487
3488 if (ImmValue == 0) {
3489 emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), Instructions);
3490 return false;
3491 }
3492
3493 switch (Inst.getOpcode()) {
3494 default:
3495 llvm_unreachable("unexpected instruction opcode");
3496 case Mips::DROLImm:
3497 if ((ImmValue >= 1) && (ImmValue <= 31)) {
3498 FirstShift = Mips::DSLL;
3499 SecondShift = Mips::DSRL32;
3500 }
3501 if (ImmValue == 32) {
3502 FirstShift = Mips::DSLL32;
3503 SecondShift = Mips::DSRL32;
3504 }
3505 if ((ImmValue >= 33) && (ImmValue <= 63)) {
3506 FirstShift = Mips::DSLL32;
3507 SecondShift = Mips::DSRL;
3508 }
3509 break;
3510 case Mips::DRORImm:
3511 if ((ImmValue >= 1) && (ImmValue <= 31)) {
3512 FirstShift = Mips::DSRL;
3513 SecondShift = Mips::DSLL32;
3514 }
3515 if (ImmValue == 32) {
3516 FirstShift = Mips::DSRL32;
3517 SecondShift = Mips::DSLL32;
3518 }
3519 if ((ImmValue >= 33) && (ImmValue <= 63)) {
3520 FirstShift = Mips::DSRL32;
3521 SecondShift = Mips::DSLL;
3522 }
3523 break;
3524 }
3525
3526 ATReg = getATReg(Inst.getLoc());
3527 if (!ATReg)
3528 return true;
3529
3530 emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), Instructions);
3531 emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32, Inst.getLoc(), Instructions);
3532 emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions);
3533
3534 return false;
3535 }
3536
3537 return true;
3538}
3539
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003540bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc,
3541 SmallVectorImpl<MCInst> &Instructions) {
3542
3543 unsigned FirstRegOp = Inst.getOperand(0).getReg();
3544 unsigned SecondRegOp = Inst.getOperand(1).getReg();
3545
3546 emitRI(Mips::BGEZ, SecondRegOp, 8, IDLoc, Instructions);
3547 if (FirstRegOp != SecondRegOp)
3548 emitRRR(Mips::ADDu, FirstRegOp, SecondRegOp, Mips::ZERO, IDLoc, Instructions);
3549 else
3550 createNop(false, IDLoc, Instructions);
3551 emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, Instructions);
3552
3553 return false;
3554}
3555
Toma Tabacu234482a2015-03-16 12:03:39 +00003556void MipsAsmParser::createNop(bool hasShortDelaySlot, SMLoc IDLoc,
3557 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003558 if (hasShortDelaySlot)
3559 emitRR(Mips::MOVE16_MM, Mips::ZERO, Mips::ZERO, IDLoc, Instructions);
3560 else
3561 emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, Instructions);
Toma Tabacu234482a2015-03-16 12:03:39 +00003562}
3563
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003564void MipsAsmParser::createAddu(unsigned DstReg, unsigned SrcReg,
Toma Tabacu0b3e9782015-06-23 14:00:54 +00003565 unsigned TrgReg, bool Is64Bit,
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003566 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanders03f9c012015-07-14 12:24:22 +00003567 emitRRR(Is64Bit ? Mips::DADDu : Mips::ADDu, DstReg, SrcReg, TrgReg, SMLoc(),
3568 Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003569}
3570
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003571void MipsAsmParser::createCpRestoreMemOp(
3572 bool IsLoad, int StackOffset, SMLoc IDLoc,
3573 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003574 // If the offset can not fit into 16 bits, we need to expand.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003575 if (!isInt<16>(StackOffset)) {
3576 MCInst MemInst;
3577 MemInst.setOpcode(IsLoad ? Mips::LW : Mips::SW);
3578 MemInst.addOperand(MCOperand::createReg(Mips::GP));
3579 MemInst.addOperand(MCOperand::createReg(Mips::SP));
3580 MemInst.addOperand(MCOperand::createImm(StackOffset));
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003581 expandMemInst(MemInst, IDLoc, Instructions, IsLoad, true /*HasImmOpnd*/);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003582 return;
3583 }
3584
3585 emitRRI(IsLoad ? Mips::LW : Mips::SW, Mips::GP, Mips::SP, StackOffset, IDLoc,
3586 Instructions);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003587}
3588
Matheus Almeida595fcab2014-06-11 15:05:56 +00003589unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
3590 // As described by the Mips32r2 spec, the registers Rd and Rs for
3591 // jalr.hb must be different.
3592 unsigned Opcode = Inst.getOpcode();
3593
3594 if (Opcode == Mips::JALR_HB &&
3595 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
3596 return Match_RequiresDifferentSrcAndDst;
3597
3598 return Match_Success;
3599}
3600
Daniel Sanders52da7af2015-11-06 12:11:03 +00003601static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
3602 uint64_t ErrorInfo) {
3603 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
3604 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
3605 if (ErrorLoc == SMLoc())
3606 return Loc;
3607 return ErrorLoc;
3608 }
3609 return Loc;
3610}
3611
David Blaikie960ea3f2014-06-08 16:18:35 +00003612bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3613 OperandVector &Operands,
3614 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003615 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00003616 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00003617
Jack Carterb4dbc172012-09-05 23:34:03 +00003618 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00003619 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00003620 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003621 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00003622
3623 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003624 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003625 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00003626 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00003627 for (unsigned i = 0; i < Instructions.size(); i++)
Akira Hatanakabd9fc282015-11-14 05:20:05 +00003628 Out.EmitInstruction(Instructions[i], getSTI());
Jack Carterb4dbc172012-09-05 23:34:03 +00003629 return false;
3630 }
3631 case Match_MissingFeature:
3632 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
3633 return true;
3634 case Match_InvalidOperand: {
3635 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00003636 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003637 if (ErrorInfo >= Operands.size())
3638 return Error(IDLoc, "too few operands for instruction");
3639
Daniel Sanders52da7af2015-11-06 12:11:03 +00003640 ErrorLoc = Operands[ErrorInfo]->getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00003641 if (ErrorLoc == SMLoc())
3642 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00003643 }
3644
3645 return Error(ErrorLoc, "invalid operand for instruction");
3646 }
3647 case Match_MnemonicFail:
3648 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00003649 case Match_RequiresDifferentSrcAndDst:
3650 return Error(IDLoc, "source and destination must be different");
Daniel Sanders52da7af2015-11-06 12:11:03 +00003651 case Match_Immz:
3652 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00003653 case Match_UImm1_0:
3654 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3655 "expected 1-bit unsigned immediate");
Daniel Sandersea4f6532015-11-06 12:22:31 +00003656 case Match_UImm2_0:
3657 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3658 "expected 2-bit unsigned immediate");
3659 case Match_UImm2_1:
3660 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3661 "expected immediate in range 1 .. 4");
Daniel Sanders38ce0f62015-11-06 12:31:27 +00003662 case Match_UImm3_0:
3663 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3664 "expected 3-bit unsigned immediate");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00003665 case Match_UImm4_0:
3666 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3667 "expected 4-bit unsigned immediate");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00003668 case Match_UImm5_0:
3669 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3670 "expected 5-bit unsigned immediate");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00003671 case Match_UImm5_1:
3672 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3673 "expected immediate in range 1 .. 32");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00003674 case Match_UImm5_32:
3675 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3676 "expected immediate in range 32 .. 63");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00003677 case Match_UImm5_33:
3678 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3679 "expected immediate in range 33 .. 64");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00003680 case Match_UImm5_0_Report_UImm6:
3681 // This is used on UImm5 operands that have a corresponding UImm5_32
3682 // operand to avoid confusing the user.
3683 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3684 "expected 6-bit unsigned immediate");
3685 case Match_UImm5_Lsl2:
3686 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3687 "expected both 7-bit unsigned immediate and multiple of 4");
Daniel Sanders59d092f2015-12-08 13:49:19 +00003688 case Match_UImm6_0:
3689 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3690 "expected 6-bit unsigned immediate");
Zlatko Buljan252cca52015-12-18 08:59:37 +00003691 case Match_SImm6:
3692 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3693 "expected 6-bit signed immediate");
3694 case Match_UImm7_0:
3695 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3696 "expected 7-bit unsigned immediate");
Daniel Sanders106d2d42015-12-08 14:42:10 +00003697 case Match_UImm8_0:
3698 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3699 "expected 8-bit unsigned immediate");
Daniel Sanders3c722312015-12-09 13:48:05 +00003700 case Match_UImm10_0:
3701 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3702 "expected 10-bit unsigned immediate");
Jack Carterb4dbc172012-09-05 23:34:03 +00003703 }
Craig Topper589ceee2015-01-03 08:16:34 +00003704
3705 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00003706}
3707
Toma Tabacud9d344b2015-04-27 14:05:04 +00003708void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
3709 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
3710 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
3711 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003712}
3713
Toma Tabacu81496c12015-05-20 08:54:45 +00003714void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
3715 if (!AssemblerOptions.back()->isMacro())
3716 Warning(Loc, "macro instruction expanded into multiple instructions");
3717}
3718
Daniel Sandersef638fe2014-10-03 15:37:37 +00003719void
3720MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
3721 SMRange Range, bool ShowColors) {
3722 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00003723 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00003724 ShowColors);
3725}
3726
Jack Carter1ac53222013-02-20 23:11:17 +00003727int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003728 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003729
Vladimir Medic4c299852013-11-06 11:27:05 +00003730 CC = StringSwitch<unsigned>(Name)
3731 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003732 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00003733 .Case("a0", 4)
3734 .Case("a1", 5)
3735 .Case("a2", 6)
3736 .Case("a3", 7)
3737 .Case("v0", 2)
3738 .Case("v1", 3)
3739 .Case("s0", 16)
3740 .Case("s1", 17)
3741 .Case("s2", 18)
3742 .Case("s3", 19)
3743 .Case("s4", 20)
3744 .Case("s5", 21)
3745 .Case("s6", 22)
3746 .Case("s7", 23)
3747 .Case("k0", 26)
3748 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003749 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00003750 .Case("sp", 29)
3751 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003752 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00003753 .Case("ra", 31)
3754 .Case("t0", 8)
3755 .Case("t1", 9)
3756 .Case("t2", 10)
3757 .Case("t3", 11)
3758 .Case("t4", 12)
3759 .Case("t5", 13)
3760 .Case("t6", 14)
3761 .Case("t7", 15)
3762 .Case("t8", 24)
3763 .Case("t9", 25)
3764 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003765
Toma Tabacufda445c2014-09-15 15:33:01 +00003766 if (!(isABI_N32() || isABI_N64()))
3767 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003768
Daniel Sandersef638fe2014-10-03 15:37:37 +00003769 if (12 <= CC && CC <= 15) {
3770 // Name is one of t4-t7
3771 AsmToken RegTok = getLexer().peekTok();
3772 SMRange RegRange = RegTok.getLocRange();
3773
3774 StringRef FixedName = StringSwitch<StringRef>(Name)
3775 .Case("t4", "t0")
3776 .Case("t5", "t1")
3777 .Case("t6", "t2")
3778 .Case("t7", "t3")
3779 .Default("");
3780 assert(FixedName != "" && "Register name is not one of t4-t7.");
3781
3782 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
3783 "Did you mean $" + FixedName + "?", RegRange);
3784 }
3785
Toma Tabacufda445c2014-09-15 15:33:01 +00003786 // Although SGI documentation just cuts out t0-t3 for n32/n64,
3787 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
3788 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
3789 if (8 <= CC && CC <= 11)
3790 CC += 4;
3791
3792 if (CC == -1)
3793 CC = StringSwitch<unsigned>(Name)
3794 .Case("a4", 8)
3795 .Case("a5", 9)
3796 .Case("a6", 10)
3797 .Case("a7", 11)
3798 .Case("kt0", 26)
3799 .Case("kt1", 27)
3800 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003801
3802 return CC;
3803}
Jack Carterd0bd6422013-04-18 00:41:53 +00003804
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003805int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
3806 int CC;
3807
3808 CC = StringSwitch<unsigned>(Name)
3809 .Case("hwr_cpunum", 0)
3810 .Case("hwr_synci_step", 1)
3811 .Case("hwr_cc", 2)
3812 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00003813 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003814 .Default(-1);
3815
3816 return CC;
3817}
3818
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003819int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003820
Jack Cartera63b16a2012-09-07 00:23:42 +00003821 if (Name[0] == 'f') {
3822 StringRef NumString = Name.substr(1);
3823 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003824 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003825 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003826 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00003827 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003828 return IntVal;
3829 }
3830 return -1;
3831}
Jack Cartera63b16a2012-09-07 00:23:42 +00003832
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003833int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
3834
3835 if (Name.startswith("fcc")) {
3836 StringRef NumString = Name.substr(3);
3837 unsigned IntVal;
3838 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003839 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003840 if (IntVal > 7) // There are only 8 fcc registers.
3841 return -1;
3842 return IntVal;
3843 }
3844 return -1;
3845}
3846
3847int MipsAsmParser::matchACRegisterName(StringRef Name) {
3848
Akira Hatanaka274d24c2013-08-14 01:15:52 +00003849 if (Name.startswith("ac")) {
3850 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003851 unsigned IntVal;
3852 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003853 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003854 if (IntVal > 3) // There are only 3 acc registers.
3855 return -1;
3856 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00003857 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003858 return -1;
3859}
Jack Carterd0bd6422013-04-18 00:41:53 +00003860
Jack Carter5dc8ac92013-09-25 23:50:44 +00003861int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
3862 unsigned IntVal;
3863
3864 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
3865 return -1;
3866
3867 if (IntVal > 31)
3868 return -1;
3869
3870 return IntVal;
3871}
3872
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003873int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
3874 int CC;
3875
3876 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00003877 .Case("msair", 0)
3878 .Case("msacsr", 1)
3879 .Case("msaaccess", 2)
3880 .Case("msasave", 3)
3881 .Case("msamodify", 4)
3882 .Case("msarequest", 5)
3883 .Case("msamap", 6)
3884 .Case("msaunmap", 7)
3885 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003886
3887 return CC;
3888}
3889
Toma Tabacu89a712b2015-04-15 10:48:56 +00003890unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00003891 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00003892 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00003893 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00003894 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00003895 return 0;
3896 }
3897 unsigned AT = getReg(
3898 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00003899 return AT;
3900}
Jack Carter0b744b32012-10-04 02:29:46 +00003901
Jack Carterd0bd6422013-04-18 00:41:53 +00003902unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00003903 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00003904}
3905
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003906unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003907 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00003908 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003909}
3910
Jack Carter873c7242013-01-12 01:03:14 +00003911int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003912 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00003913 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00003914 return -1;
3915
Jack Carter873c7242013-01-12 01:03:14 +00003916 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00003917}
3918
Toma Tabacu13964452014-09-04 13:23:44 +00003919bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003920 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00003921 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003922
Jack Carter30a59822012-10-04 04:03:53 +00003923 // Check if the current operand has a custom associated parser, if so, try to
3924 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00003925 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3926 if (ResTy == MatchOperand_Success)
3927 return false;
3928 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3929 // there was a match, but an error occurred, in which case, just return that
3930 // the operand parsing failed.
3931 if (ResTy == MatchOperand_ParseFail)
3932 return true;
3933
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003934 DEBUG(dbgs() << ".. Generic Parser\n");
3935
Jack Carterb4dbc172012-09-05 23:34:03 +00003936 switch (getLexer().getKind()) {
3937 default:
3938 Error(Parser.getTok().getLoc(), "unexpected token in operand");
3939 return true;
3940 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003941 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00003942 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00003943
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003944 // Almost all registers have been parsed by custom parsers. There is only
3945 // one exception to this. $zero (and it's alias $0) will reach this point
3946 // for div, divu, and similar instructions because it is not an operand
3947 // to the instruction definition but an explicit register. Special case
3948 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00003949 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00003950 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003951
Jack Carterd0bd6422013-04-18 00:41:53 +00003952 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00003953 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003954 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00003955 return true;
3956
Jack Carter873c7242013-01-12 01:03:14 +00003957 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00003958 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00003959 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00003960 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003961 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00003962
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003963 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003964 return false;
3965 }
Vladimir Medic4c299852013-11-06 11:27:05 +00003966 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00003967 case AsmToken::LParen:
3968 case AsmToken::Minus:
3969 case AsmToken::Plus:
3970 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00003971 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00003972 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003973 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00003974 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003975 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00003976 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00003977 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003978 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003979 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003980 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00003981 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00003982 return true;
3983
Jack Carter873c7242013-01-12 01:03:14 +00003984 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3985
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003986 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00003987 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003988 } // case AsmToken::Percent
3989 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00003990 return true;
3991}
3992
Vladimir Medic4c299852013-11-06 11:27:05 +00003993const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00003994 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00003995 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00003996 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00003997 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00003998 // It's a constant, evaluate reloc value.
3999 int16_t Val;
4000 switch (getVariantKind(RelocStr)) {
4001 case MCSymbolRefExpr::VK_Mips_ABS_LO:
4002 // Get the 1st 16-bits.
4003 Val = MCE->getValue() & 0xffff;
4004 break;
4005 case MCSymbolRefExpr::VK_Mips_ABS_HI:
4006 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
4007 // 16 bits being negative.
4008 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
4009 break;
4010 case MCSymbolRefExpr::VK_Mips_HIGHER:
4011 // Get the 3rd 16-bits.
4012 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
4013 break;
4014 case MCSymbolRefExpr::VK_Mips_HIGHEST:
4015 // Get the 4th 16-bits.
4016 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
4017 break;
4018 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00004019 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00004020 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00004021 return MCConstantExpr::create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00004022 }
4023
Jack Carterb5cf5902013-04-17 00:18:04 +00004024 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004025 // It's a symbol, create a symbolic expression from the symbol.
Toma Tabacu07c97b32015-06-17 10:43:45 +00004026 const MCSymbol *Symbol = &MSRE->getSymbol();
Jack Carterb5cf5902013-04-17 00:18:04 +00004027 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004028 Res = MCSymbolRefExpr::create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004029 return Res;
4030 }
4031
4032 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00004033 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
4034
Sasa Stankovic06c47802014-04-03 10:37:45 +00004035 // Try to create target expression.
4036 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
Jim Grosbach13760bd2015-05-30 01:25:56 +00004037 return MipsMCExpr::create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00004038
Jack Carterd0bd6422013-04-18 00:41:53 +00004039 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
4040 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004041 Res = MCBinaryExpr::create(BE->getOpcode(), LExp, RExp, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004042 return Res;
4043 }
4044
4045 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004046 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004047 Res = MCUnaryExpr::create(UN->getOpcode(), UnExp, getContext());
Jack Carterd0bd6422013-04-18 00:41:53 +00004048 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00004049 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004050 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00004051 return Expr;
4052}
4053
4054bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
4055
4056 switch (Expr->getKind()) {
4057 case MCExpr::Constant:
4058 return true;
4059 case MCExpr::SymbolRef:
4060 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
4061 case MCExpr::Binary:
4062 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
4063 if (!isEvaluated(BE->getLHS()))
4064 return false;
4065 return isEvaluated(BE->getRHS());
4066 }
4067 case MCExpr::Unary:
4068 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00004069 case MCExpr::Target:
4070 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004071 }
Jack Carterb5cf5902013-04-17 00:18:04 +00004072 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00004073}
Jack Carterd0bd6422013-04-18 00:41:53 +00004074
Jack Carterb5cf5902013-04-17 00:18:04 +00004075bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004076 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00004077 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00004078 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00004079 if (Tok.isNot(AsmToken::Identifier))
4080 return true;
4081
Yaron Keren075759a2015-03-30 15:42:36 +00004082 std::string Str = Tok.getIdentifier();
Jack Carterb5cf5902013-04-17 00:18:04 +00004083
Jack Carterd0bd6422013-04-18 00:41:53 +00004084 Parser.Lex(); // Eat the identifier.
4085 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004086 const MCExpr *IdVal;
4087 SMLoc EndLoc;
4088
4089 if (getLexer().getKind() == AsmToken::LParen) {
4090 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004091 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004092 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004093 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004094 const AsmToken &nextTok = Parser.getTok();
4095 if (nextTok.isNot(AsmToken::Identifier))
4096 return true;
4097 Str += "(%";
4098 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00004099 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00004100 if (getLexer().getKind() != AsmToken::LParen)
4101 return true;
4102 } else
4103 break;
4104 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004105 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00004106 return true;
4107
4108 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00004109 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004110
4111 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00004112 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004113
Jack Carterd0bd6422013-04-18 00:41:53 +00004114 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00004115 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004116}
4117
Jack Carterb4dbc172012-09-05 23:34:03 +00004118bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
4119 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004120 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00004121 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004122 if (ResTy == MatchOperand_Success) {
4123 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00004124 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004125 StartLoc = Operand.getStartLoc();
4126 EndLoc = Operand.getEndLoc();
4127
4128 // AFAIK, we only support numeric registers and named GPR's in CFI
4129 // directives.
4130 // Don't worry about eating tokens before failing. Using an unrecognised
4131 // register is a parse error.
4132 if (Operand.isGPRAsmReg()) {
4133 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004134 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004135 }
4136
4137 return (RegNo == (unsigned)-1);
4138 }
4139
4140 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00004141 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00004142}
4143
Jack Carterb5cf5902013-04-17 00:18:04 +00004144bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004145 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00004146 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00004147 bool Result = true;
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004148 unsigned NumOfLParen = 0;
Jack Carterb5cf5902013-04-17 00:18:04 +00004149
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004150 while (getLexer().getKind() == AsmToken::LParen) {
Jack Carterb5cf5902013-04-17 00:18:04 +00004151 Parser.Lex();
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004152 ++NumOfLParen;
4153 }
Jack Carter873c7242013-01-12 01:03:14 +00004154
Jack Carterd0bd6422013-04-18 00:41:53 +00004155 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00004156 default:
4157 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00004158 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00004159 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00004160 case AsmToken::Integer:
4161 case AsmToken::Minus:
4162 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00004163 if (isParenExpr)
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004164 Result = getParser().parseParenExprOfDepth(NumOfLParen, Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00004165 else
4166 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00004167 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00004168 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004169 break;
Jack Carter873c7242013-01-12 01:03:14 +00004170 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00004171 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00004172 }
Jack Carterb5cf5902013-04-17 00:18:04 +00004173 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004174}
4175
David Blaikie960ea3f2014-06-08 16:18:35 +00004176MipsAsmParser::OperandMatchResultTy
4177MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004178 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004179 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00004180 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00004181 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00004182 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004183 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00004184 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00004185 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00004186
Jack Carterb5cf5902013-04-17 00:18:04 +00004187 if (getLexer().getKind() == AsmToken::LParen) {
4188 Parser.Lex();
4189 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004190 }
4191
Jack Carterb5cf5902013-04-17 00:18:04 +00004192 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004193 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00004194 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004195
Jack Carterd0bd6422013-04-18 00:41:53 +00004196 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004197 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004198 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00004199 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00004200 SMLoc E =
4201 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004202 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00004203 return MatchOperand_Success;
4204 }
4205 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004206 SMLoc E =
4207 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00004208
Jack Carterd0bd6422013-04-18 00:41:53 +00004209 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004210 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00004211 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004212 S, E, *this);
4213 Operands.push_back(
4214 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00004215 return MatchOperand_Success;
4216 }
4217 Error(Parser.getTok().getLoc(), "'(' expected");
4218 return MatchOperand_ParseFail;
4219 }
4220
Jack Carterd0bd6422013-04-18 00:41:53 +00004221 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004222 }
4223
Toma Tabacu13964452014-09-04 13:23:44 +00004224 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004225 if (Res != MatchOperand_Success)
4226 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004227
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004228 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00004229 Error(Parser.getTok().getLoc(), "')' expected");
4230 return MatchOperand_ParseFail;
4231 }
4232
Jack Carter873c7242013-01-12 01:03:14 +00004233 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4234
Jack Carterd0bd6422013-04-18 00:41:53 +00004235 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004236
Craig Topper062a2ba2014-04-25 05:30:21 +00004237 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004238 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00004239
Jack Carterd0bd6422013-04-18 00:41:53 +00004240 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00004241 std::unique_ptr<MipsOperand> op(
4242 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00004243 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004244 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004245 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00004246 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004247 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
4248 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004249 if (IdVal->evaluateAsAbsolute(Imm))
4250 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004251 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004252 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00004253 getContext());
4254 }
4255
David Blaikie960ea3f2014-06-08 16:18:35 +00004256 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004257 return MatchOperand_Success;
4258}
4259
David Blaikie960ea3f2014-06-08 16:18:35 +00004260bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004261 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00004262 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00004263 if (Sym) {
4264 SMLoc S = Parser.getTok().getLoc();
4265 const MCExpr *Expr;
4266 if (Sym->isVariable())
4267 Expr = Sym->getVariableValue();
4268 else
4269 return false;
4270 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004271 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00004272 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00004273 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004274 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004275 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00004276 if (ResTy == MatchOperand_Success) {
4277 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00004278 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00004279 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004280 llvm_unreachable("Should never ParseFail");
4281 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00004282 }
4283 } else if (Expr->getKind() == MCExpr::Constant) {
4284 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00004285 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00004286 Operands.push_back(
4287 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00004288 return true;
4289 }
4290 }
4291 return false;
4292}
Jack Carterd0bd6422013-04-18 00:41:53 +00004293
Jack Carter873c7242013-01-12 01:03:14 +00004294MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004295MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00004296 StringRef Identifier,
4297 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004298 int Index = matchCPURegisterName(Identifier);
4299 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004300 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004301 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4302 return MatchOperand_Success;
4303 }
4304
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004305 Index = matchHWRegsRegisterName(Identifier);
4306 if (Index != -1) {
4307 Operands.push_back(MipsOperand::createHWRegsReg(
4308 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4309 return MatchOperand_Success;
4310 }
4311
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004312 Index = matchFPURegisterName(Identifier);
4313 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004314 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004315 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4316 return MatchOperand_Success;
4317 }
4318
4319 Index = matchFCCRegisterName(Identifier);
4320 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004321 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004322 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4323 return MatchOperand_Success;
4324 }
4325
4326 Index = matchACRegisterName(Identifier);
4327 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004328 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004329 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4330 return MatchOperand_Success;
4331 }
4332
4333 Index = matchMSA128RegisterName(Identifier);
4334 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004335 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004336 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4337 return MatchOperand_Success;
4338 }
4339
4340 Index = matchMSA128CtrlRegisterName(Identifier);
4341 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004342 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004343 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4344 return MatchOperand_Success;
4345 }
4346
4347 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00004348}
4349
4350MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004351MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004352 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00004353 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004354
4355 if (Token.is(AsmToken::Identifier)) {
4356 DEBUG(dbgs() << ".. identifier\n");
4357 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00004358 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004359 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00004360 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004361 } else if (Token.is(AsmToken::Integer)) {
4362 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00004363 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004364 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
4365 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004366 return MatchOperand_Success;
4367 }
4368
4369 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
4370
4371 return MatchOperand_NoMatch;
4372}
4373
David Blaikie960ea3f2014-06-08 16:18:35 +00004374MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004375MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004376 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004377 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004378
4379 auto Token = Parser.getTok();
4380
4381 SMLoc S = Token.getLoc();
4382
4383 if (Token.isNot(AsmToken::Dollar)) {
4384 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
4385 if (Token.is(AsmToken::Identifier)) {
4386 if (searchSymbolAlias(Operands))
4387 return MatchOperand_Success;
4388 }
4389 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
4390 return MatchOperand_NoMatch;
4391 }
4392 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004393
Toma Tabacu13964452014-09-04 13:23:44 +00004394 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00004395 if (ResTy == MatchOperand_Success) {
4396 Parser.Lex(); // $
4397 Parser.Lex(); // identifier
4398 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004399 return ResTy;
4400}
4401
4402MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004403MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004404 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004405 switch (getLexer().getKind()) {
4406 default:
4407 return MatchOperand_NoMatch;
4408 case AsmToken::LParen:
4409 case AsmToken::Minus:
4410 case AsmToken::Plus:
4411 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00004412 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004413 case AsmToken::String:
4414 break;
4415 }
4416
4417 const MCExpr *IdVal;
4418 SMLoc S = Parser.getTok().getLoc();
4419 if (getParser().parseExpression(IdVal))
4420 return MatchOperand_ParseFail;
4421
4422 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4423 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
4424 return MatchOperand_Success;
4425}
4426
David Blaikie960ea3f2014-06-08 16:18:35 +00004427MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004428MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004429 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004430 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004431
4432 SMLoc S = getLexer().getLoc();
4433
4434 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00004435 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004436 if (ResTy != MatchOperand_NoMatch)
4437 return ResTy;
4438
Daniel Sanders315386c2014-04-01 10:40:14 +00004439 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00004440 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00004441 if (ResTy != MatchOperand_NoMatch)
4442 return ResTy;
4443
Daniel Sandersffd84362014-04-01 10:41:48 +00004444 const MCExpr *Expr = nullptr;
4445 if (Parser.parseExpression(Expr)) {
4446 // We have no way of knowing if a symbol was consumed so we must ParseFail
4447 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004448 }
Daniel Sandersffd84362014-04-01 10:41:48 +00004449 Operands.push_back(
4450 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004451 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00004452}
4453
Vladimir Medic2b953d02013-10-01 09:48:56 +00004454MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00004455MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004456 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00004457 const MCExpr *IdVal;
4458 // If the first token is '$' we may have register operand.
4459 if (Parser.getTok().is(AsmToken::Dollar))
4460 return MatchOperand_NoMatch;
4461 SMLoc S = Parser.getTok().getLoc();
4462 if (getParser().parseExpression(IdVal))
4463 return MatchOperand_ParseFail;
4464 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00004465 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00004466 int64_t Val = MCE->getValue();
4467 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4468 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00004469 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00004470 return MatchOperand_Success;
4471}
4472
Matheus Almeida779c5932013-11-18 12:32:49 +00004473MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004474MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004475 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00004476 switch (getLexer().getKind()) {
4477 default:
4478 return MatchOperand_NoMatch;
4479 case AsmToken::LParen:
4480 case AsmToken::Plus:
4481 case AsmToken::Minus:
4482 case AsmToken::Integer:
4483 break;
4484 }
4485
4486 const MCExpr *Expr;
4487 SMLoc S = Parser.getTok().getLoc();
4488
4489 if (getParser().parseExpression(Expr))
4490 return MatchOperand_ParseFail;
4491
4492 int64_t Val;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004493 if (!Expr->evaluateAsAbsolute(Val)) {
Matheus Almeida779c5932013-11-18 12:32:49 +00004494 Error(S, "expected immediate value");
4495 return MatchOperand_ParseFail;
4496 }
4497
4498 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
4499 // and because the CPU always adds one to the immediate field, the allowed
4500 // range becomes 1..4. We'll only check the range here and will deal
4501 // with the addition/subtraction when actually decoding/encoding
4502 // the instruction.
4503 if (Val < 1 || Val > 4) {
4504 Error(S, "immediate not in range (1..4)");
4505 return MatchOperand_ParseFail;
4506 }
4507
Jack Carter3b2c96e2014-01-22 23:31:38 +00004508 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004509 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00004510 return MatchOperand_Success;
4511}
4512
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004513MipsAsmParser::OperandMatchResultTy
4514MipsAsmParser::parseRegisterList(OperandVector &Operands) {
4515 MCAsmParser &Parser = getParser();
4516 SmallVector<unsigned, 10> Regs;
4517 unsigned RegNo;
4518 unsigned PrevReg = Mips::NoRegister;
4519 bool RegRange = false;
4520 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4521
4522 if (Parser.getTok().isNot(AsmToken::Dollar))
4523 return MatchOperand_ParseFail;
4524
4525 SMLoc S = Parser.getTok().getLoc();
4526 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
4527 SMLoc E = getLexer().getLoc();
4528 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
4529 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
4530 if (RegRange) {
4531 // Remove last register operand because registers from register range
4532 // should be inserted first.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004533 if ((isGP64bit() && RegNo == Mips::RA_64) ||
4534 (!isGP64bit() && RegNo == Mips::RA)) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004535 Regs.push_back(RegNo);
4536 } else {
4537 unsigned TmpReg = PrevReg + 1;
4538 while (TmpReg <= RegNo) {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004539 if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) ||
4540 (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) &&
4541 isGP64bit())) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004542 Error(E, "invalid register operand");
4543 return MatchOperand_ParseFail;
4544 }
4545
4546 PrevReg = TmpReg;
4547 Regs.push_back(TmpReg++);
4548 }
4549 }
4550
4551 RegRange = false;
4552 } else {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004553 if ((PrevReg == Mips::NoRegister) &&
4554 ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) ||
4555 (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA)))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004556 Error(E, "$16 or $31 expected");
4557 return MatchOperand_ParseFail;
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004558 } else if (!(((RegNo == Mips::FP || RegNo == Mips::RA ||
4559 (RegNo >= Mips::S0 && RegNo <= Mips::S7)) &&
4560 !isGP64bit()) ||
4561 ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 ||
4562 (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) &&
4563 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004564 Error(E, "invalid register operand");
4565 return MatchOperand_ParseFail;
4566 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004567 ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) ||
4568 (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 &&
4569 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004570 Error(E, "consecutive register numbers expected");
4571 return MatchOperand_ParseFail;
4572 }
4573
4574 Regs.push_back(RegNo);
4575 }
4576
4577 if (Parser.getTok().is(AsmToken::Minus))
4578 RegRange = true;
4579
4580 if (!Parser.getTok().isNot(AsmToken::Minus) &&
4581 !Parser.getTok().isNot(AsmToken::Comma)) {
4582 Error(E, "',' or '-' expected");
4583 return MatchOperand_ParseFail;
4584 }
4585
4586 Lex(); // Consume comma or minus
4587 if (Parser.getTok().isNot(AsmToken::Dollar))
4588 break;
4589
4590 PrevReg = RegNo;
4591 }
4592
4593 SMLoc E = Parser.getTok().getLoc();
4594 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4595 parseMemOperand(Operands);
4596 return MatchOperand_Success;
4597}
4598
Zoran Jovanovic2deca342014-12-16 14:59:10 +00004599MipsAsmParser::OperandMatchResultTy
4600MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
4601 MCAsmParser &Parser = getParser();
4602
4603 SMLoc S = Parser.getTok().getLoc();
4604 if (parseAnyRegister(Operands) != MatchOperand_Success)
4605 return MatchOperand_ParseFail;
4606
4607 SMLoc E = Parser.getTok().getLoc();
4608 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
4609 unsigned Reg = Op.getGPR32Reg();
4610 Operands.pop_back();
4611 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
4612 return MatchOperand_Success;
4613}
4614
Zoran Jovanovic41688672015-02-10 16:36:20 +00004615MipsAsmParser::OperandMatchResultTy
4616MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
4617 MCAsmParser &Parser = getParser();
4618 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4619 SmallVector<unsigned, 10> Regs;
4620
4621 if (Parser.getTok().isNot(AsmToken::Dollar))
4622 return MatchOperand_ParseFail;
4623
4624 SMLoc S = Parser.getTok().getLoc();
4625
4626 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4627 return MatchOperand_ParseFail;
4628
4629 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4630 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4631 Regs.push_back(RegNo);
4632
4633 SMLoc E = Parser.getTok().getLoc();
4634 if (Parser.getTok().isNot(AsmToken::Comma)) {
4635 Error(E, "',' expected");
4636 return MatchOperand_ParseFail;
4637 }
4638
4639 // Remove comma.
4640 Parser.Lex();
4641
4642 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4643 return MatchOperand_ParseFail;
4644
4645 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4646 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4647 Regs.push_back(RegNo);
4648
4649 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4650
4651 return MatchOperand_Success;
4652}
4653
Jack Carterdc1e35d2012-09-06 20:00:02 +00004654MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
4655
Vladimir Medic4c299852013-11-06 11:27:05 +00004656 MCSymbolRefExpr::VariantKind VK =
4657 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
4658 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
4659 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
4660 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
4661 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
4662 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
4663 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
4664 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
4665 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
4666 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
4667 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
4668 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
4669 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
4670 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
4671 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
4672 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
4673 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
4674 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00004675 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
4676 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
4677 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
4678 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
4679 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
4680 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00004681 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
4682 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00004683 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00004684
Matheus Almeida2852af82014-04-22 10:15:54 +00004685 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00004686
Jack Carterdc1e35d2012-09-06 20:00:02 +00004687 return VK;
4688}
Jack Cartera63b16a2012-09-07 00:23:42 +00004689
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004690/// Sometimes (i.e. load/stores) the operand may be followed immediately by
4691/// either this.
4692/// ::= '(', register, ')'
4693/// handle it before we iterate so we don't get tripped up by the lack of
4694/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004695bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004696 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004697 if (getLexer().is(AsmToken::LParen)) {
4698 Operands.push_back(
4699 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
4700 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004701 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004702 SMLoc Loc = getLexer().getLoc();
4703 Parser.eatToEndOfStatement();
4704 return Error(Loc, "unexpected token in argument list");
4705 }
4706 if (Parser.getTok().isNot(AsmToken::RParen)) {
4707 SMLoc Loc = getLexer().getLoc();
4708 Parser.eatToEndOfStatement();
4709 return Error(Loc, "unexpected token, expected ')'");
4710 }
4711 Operands.push_back(
4712 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
4713 Parser.Lex();
4714 }
4715 return false;
4716}
4717
4718/// Sometimes (i.e. in MSA) the operand may be followed immediately by
4719/// either one of these.
4720/// ::= '[', register, ']'
4721/// ::= '[', integer, ']'
4722/// handle it before we iterate so we don't get tripped up by the lack of
4723/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004724bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00004725 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004726 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004727 if (getLexer().is(AsmToken::LBrac)) {
4728 Operands.push_back(
4729 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
4730 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004731 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004732 SMLoc Loc = getLexer().getLoc();
4733 Parser.eatToEndOfStatement();
4734 return Error(Loc, "unexpected token in argument list");
4735 }
4736 if (Parser.getTok().isNot(AsmToken::RBrac)) {
4737 SMLoc Loc = getLexer().getLoc();
4738 Parser.eatToEndOfStatement();
4739 return Error(Loc, "unexpected token, expected ']'");
4740 }
4741 Operands.push_back(
4742 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
4743 Parser.Lex();
4744 }
4745 return false;
4746}
4747
David Blaikie960ea3f2014-06-08 16:18:35 +00004748bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
4749 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004750 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004751 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004752
4753 // We have reached first instruction, module directive are now forbidden.
4754 getTargetStreamer().forbidModuleDirective();
4755
Vladimir Medic74593e62013-07-17 15:00:42 +00004756 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00004757 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00004758 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00004759 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00004760 }
Vladimir Medic64828a12013-07-16 10:07:14 +00004761 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004762 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004763
4764 // Read the remaining operands.
4765 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4766 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004767 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004768 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004769 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004770 return Error(Loc, "unexpected token in argument list");
4771 }
Toma Tabacu13964452014-09-04 13:23:44 +00004772 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004773 return true;
4774 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00004775
Jack Carterd0bd6422013-04-18 00:41:53 +00004776 while (getLexer().is(AsmToken::Comma)) {
4777 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00004778 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004779 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004780 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004781 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004782 return Error(Loc, "unexpected token in argument list");
4783 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004784 // Parse bracket and parenthesis suffixes before we iterate
4785 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00004786 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004787 return true;
4788 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00004789 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004790 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00004791 }
4792 }
Jack Carterb4dbc172012-09-05 23:34:03 +00004793 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4794 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004795 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004796 return Error(Loc, "unexpected token in argument list");
4797 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004798 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00004799 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00004800}
4801
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004802bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004803 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004804 SMLoc Loc = getLexer().getLoc();
4805 Parser.eatToEndOfStatement();
4806 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00004807}
4808
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004809bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004810 return Error(Loc, ErrorMsg);
4811}
4812
Jack Carter0b744b32012-10-04 02:29:46 +00004813bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004814 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004815 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00004816
4817 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00004818 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00004819
4820 Parser.Lex(); // Eat "noat".
4821
Jack Carterd0bd6422013-04-18 00:41:53 +00004822 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004823 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004824 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004825 return false;
4826 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004827
4828 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004829 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004830 return false;
4831}
Jack Carterd0bd6422013-04-18 00:41:53 +00004832
Jack Carter0b744b32012-10-04 02:29:46 +00004833bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00004834 // Line can be: ".set at", which sets $at to $1
4835 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00004836 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00004837 Parser.Lex(); // Eat "at".
4838
Jack Carter0b744b32012-10-04 02:29:46 +00004839 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004840 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00004841 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00004842
4843 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004844 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004845 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00004846 }
4847
4848 if (getLexer().isNot(AsmToken::Equal)) {
4849 reportParseError("unexpected token, expected equals sign");
4850 return false;
4851 }
4852 Parser.Lex(); // Eat "=".
4853
4854 if (getLexer().isNot(AsmToken::Dollar)) {
4855 if (getLexer().is(AsmToken::EndOfStatement)) {
4856 reportParseError("no register specified");
4857 return false;
4858 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00004859 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00004860 return false;
4861 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004862 }
4863 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00004864
Toma Tabacu16a74492015-02-13 10:30:57 +00004865 // Find out what "reg" is.
4866 unsigned AtRegNo;
4867 const AsmToken &Reg = Parser.getTok();
4868 if (Reg.is(AsmToken::Identifier)) {
4869 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
4870 } else if (Reg.is(AsmToken::Integer)) {
4871 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00004872 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00004873 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00004874 return false;
4875 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004876
4877 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00004878 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004879 reportParseError("invalid register");
4880 return false;
4881 }
4882 Parser.Lex(); // Eat "reg".
4883
4884 // If this is not the end of the statement, report an error.
4885 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4886 reportParseError("unexpected token, expected end of statement");
4887 return false;
4888 }
4889
4890 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
4891
4892 Parser.Lex(); // Consume the EndOfStatement.
4893 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004894}
4895
4896bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004897 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004898 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004899 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004900 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004901 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004902 return false;
4903 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004904 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00004905 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004906 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004907 return false;
4908}
4909
4910bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004911 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004912 Parser.Lex();
4913 // If this is not the end of the statement, report an error.
4914 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004915 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004916 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00004917 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004918 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00004919 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004920 Parser.Lex(); // Consume the EndOfStatement.
4921 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004922}
4923
4924bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004925 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004926 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004927 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004928 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004929 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004930 return false;
4931 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004932 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00004933 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00004934 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004935 return false;
4936}
4937
4938bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004939 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004940 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004941 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004942 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004943 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004944 return false;
4945 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004946 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00004947 reportParseError("`noreorder' must be set before `nomacro'");
4948 return false;
4949 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004950 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00004951 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00004952 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004953 return false;
4954}
Jack Carterd76b2372013-03-21 21:44:16 +00004955
Daniel Sanders44934432014-08-07 12:03:36 +00004956bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004957 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00004958 Parser.Lex();
4959
4960 // If this is not the end of the statement, report an error.
4961 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004962 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00004963
4964 setFeatureBits(Mips::FeatureMSA, "msa");
4965 getTargetStreamer().emitDirectiveSetMsa();
4966 return false;
4967}
4968
4969bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004970 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00004971 Parser.Lex();
4972
4973 // If this is not the end of the statement, report an error.
4974 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004975 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00004976
4977 clearFeatureBits(Mips::FeatureMSA, "msa");
4978 getTargetStreamer().emitDirectiveSetNoMsa();
4979 return false;
4980}
4981
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004982bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004983 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004984 Parser.Lex(); // Eat "nodsp".
4985
4986 // If this is not the end of the statement, report an error.
4987 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4988 reportParseError("unexpected token, expected end of statement");
4989 return false;
4990 }
4991
4992 clearFeatureBits(Mips::FeatureDSP, "dsp");
4993 getTargetStreamer().emitDirectiveSetNoDsp();
4994 return false;
4995}
4996
Toma Tabacucc2502d2014-11-04 17:18:07 +00004997bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004998 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00004999 Parser.Lex(); // Eat "mips16".
5000
Jack Carter39536722014-01-22 23:08:42 +00005001 // If this is not the end of the statement, report an error.
5002 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005003 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00005004 return false;
5005 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00005006
5007 setFeatureBits(Mips::FeatureMips16, "mips16");
5008 getTargetStreamer().emitDirectiveSetMips16();
5009 Parser.Lex(); // Consume the EndOfStatement.
5010 return false;
5011}
5012
5013bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005014 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005015 Parser.Lex(); // Eat "nomips16".
5016
5017 // If this is not the end of the statement, report an error.
5018 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5019 reportParseError("unexpected token, expected end of statement");
5020 return false;
5021 }
5022
5023 clearFeatureBits(Mips::FeatureMips16, "mips16");
5024 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00005025 Parser.Lex(); // Consume the EndOfStatement.
5026 return false;
5027}
5028
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005029bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005030 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005031 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005032 // Line can be: .set fp=32
5033 // .set fp=xx
5034 // .set fp=64
5035 Parser.Lex(); // Eat fp token
5036 AsmToken Tok = Parser.getTok();
5037 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005038 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005039 return false;
5040 }
5041 Parser.Lex(); // Eat '=' token.
5042 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005043
5044 if (!parseFpABIValue(FpAbiVal, ".set"))
5045 return false;
5046
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005047 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005048 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005049 return false;
5050 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005051 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005052 Parser.Lex(); // Consume the EndOfStatement.
5053 return false;
5054}
5055
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005056bool MipsAsmParser::parseSetOddSPRegDirective() {
5057 MCAsmParser &Parser = getParser();
5058
5059 Parser.Lex(); // Eat "oddspreg".
5060 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5061 reportParseError("unexpected token, expected end of statement");
5062 return false;
5063 }
5064
5065 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5066 getTargetStreamer().emitDirectiveSetOddSPReg();
5067 return false;
5068}
5069
5070bool MipsAsmParser::parseSetNoOddSPRegDirective() {
5071 MCAsmParser &Parser = getParser();
5072
5073 Parser.Lex(); // Eat "nooddspreg".
5074 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5075 reportParseError("unexpected token, expected end of statement");
5076 return false;
5077 }
5078
5079 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5080 getTargetStreamer().emitDirectiveSetNoOddSPReg();
5081 return false;
5082}
5083
Toma Tabacu9db22db2014-09-09 10:15:38 +00005084bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005085 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005086 SMLoc Loc = getLexer().getLoc();
5087
5088 Parser.Lex();
5089 if (getLexer().isNot(AsmToken::EndOfStatement))
5090 return reportParseError("unexpected token, expected end of statement");
5091
5092 // Always keep an element on the options "stack" to prevent the user
5093 // from changing the initial options. This is how we remember them.
5094 if (AssemblerOptions.size() == 2)
5095 return reportParseError(Loc, ".set pop with no .set push");
5096
Akira Hatanakab11ef082015-11-14 06:35:56 +00005097 MCSubtargetInfo &STI = copySTI();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005098 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005099 setAvailableFeatures(
5100 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
5101 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00005102
5103 getTargetStreamer().emitDirectiveSetPop();
5104 return false;
5105}
5106
5107bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005108 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005109 Parser.Lex();
5110 if (getLexer().isNot(AsmToken::EndOfStatement))
5111 return reportParseError("unexpected token, expected end of statement");
5112
5113 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00005114 AssemblerOptions.push_back(
5115 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00005116
5117 getTargetStreamer().emitDirectiveSetPush();
5118 return false;
5119}
5120
Toma Tabacu29696502015-06-02 09:48:04 +00005121bool MipsAsmParser::parseSetSoftFloatDirective() {
5122 MCAsmParser &Parser = getParser();
5123 Parser.Lex();
5124 if (getLexer().isNot(AsmToken::EndOfStatement))
5125 return reportParseError("unexpected token, expected end of statement");
5126
5127 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5128 getTargetStreamer().emitDirectiveSetSoftFloat();
5129 return false;
5130}
5131
5132bool MipsAsmParser::parseSetHardFloatDirective() {
5133 MCAsmParser &Parser = getParser();
5134 Parser.Lex();
5135 if (getLexer().isNot(AsmToken::EndOfStatement))
5136 return reportParseError("unexpected token, expected end of statement");
5137
5138 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5139 getTargetStreamer().emitDirectiveSetHardFloat();
5140 return false;
5141}
5142
Jack Carterd76b2372013-03-21 21:44:16 +00005143bool MipsAsmParser::parseSetAssignment() {
5144 StringRef Name;
5145 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00005146 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00005147
5148 if (Parser.parseIdentifier(Name))
5149 reportParseError("expected identifier after .set");
5150
5151 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005152 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00005153 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00005154
Jack Carter3b2c96e2014-01-22 23:31:38 +00005155 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00005156 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00005157
Jim Grosbach6f482002015-05-18 18:43:14 +00005158 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00005159 Sym->setVariableValue(Value);
5160
5161 return false;
5162}
Jack Carterd0bd6422013-04-18 00:41:53 +00005163
Toma Tabacu26647792014-09-09 12:52:14 +00005164bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005165 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00005166 Parser.Lex();
5167 if (getLexer().isNot(AsmToken::EndOfStatement))
5168 return reportParseError("unexpected token, expected end of statement");
5169
5170 // Reset assembler options to their initial values.
Akira Hatanakab11ef082015-11-14 06:35:56 +00005171 MCSubtargetInfo &STI = copySTI();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005172 setAvailableFeatures(
5173 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
5174 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00005175 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
5176
5177 getTargetStreamer().emitDirectiveSetMips0();
5178 return false;
5179}
5180
Toma Tabacu85618b32014-08-19 14:22:52 +00005181bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005182 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00005183 Parser.Lex();
5184 if (getLexer().isNot(AsmToken::Equal))
5185 return reportParseError("unexpected token, expected equals sign");
5186
5187 Parser.Lex();
5188 StringRef Arch;
5189 if (Parser.parseIdentifier(Arch))
5190 return reportParseError("expected arch identifier");
5191
5192 StringRef ArchFeatureName =
5193 StringSwitch<StringRef>(Arch)
5194 .Case("mips1", "mips1")
5195 .Case("mips2", "mips2")
5196 .Case("mips3", "mips3")
5197 .Case("mips4", "mips4")
5198 .Case("mips5", "mips5")
5199 .Case("mips32", "mips32")
5200 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005201 .Case("mips32r3", "mips32r3")
5202 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005203 .Case("mips32r6", "mips32r6")
5204 .Case("mips64", "mips64")
5205 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005206 .Case("mips64r3", "mips64r3")
5207 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005208 .Case("mips64r6", "mips64r6")
5209 .Case("cnmips", "cnmips")
5210 .Case("r4000", "mips3") // This is an implementation of Mips3.
5211 .Default("");
5212
5213 if (ArchFeatureName.empty())
5214 return reportParseError("unsupported architecture");
5215
5216 selectArch(ArchFeatureName);
5217 getTargetStreamer().emitDirectiveSetArch(Arch);
5218 return false;
5219}
5220
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005221bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005222 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005223 Parser.Lex();
5224 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005225 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005226
Matheus Almeida2852af82014-04-22 10:15:54 +00005227 switch (Feature) {
5228 default:
5229 llvm_unreachable("Unimplemented feature");
5230 case Mips::FeatureDSP:
5231 setFeatureBits(Mips::FeatureDSP, "dsp");
5232 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005233 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005234 case Mips::FeatureMicroMips:
5235 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005236 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005237 case Mips::FeatureMips1:
5238 selectArch("mips1");
5239 getTargetStreamer().emitDirectiveSetMips1();
5240 break;
5241 case Mips::FeatureMips2:
5242 selectArch("mips2");
5243 getTargetStreamer().emitDirectiveSetMips2();
5244 break;
5245 case Mips::FeatureMips3:
5246 selectArch("mips3");
5247 getTargetStreamer().emitDirectiveSetMips3();
5248 break;
5249 case Mips::FeatureMips4:
5250 selectArch("mips4");
5251 getTargetStreamer().emitDirectiveSetMips4();
5252 break;
5253 case Mips::FeatureMips5:
5254 selectArch("mips5");
5255 getTargetStreamer().emitDirectiveSetMips5();
5256 break;
5257 case Mips::FeatureMips32:
5258 selectArch("mips32");
5259 getTargetStreamer().emitDirectiveSetMips32();
5260 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005261 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005262 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005263 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005264 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005265 case Mips::FeatureMips32r3:
5266 selectArch("mips32r3");
5267 getTargetStreamer().emitDirectiveSetMips32R3();
5268 break;
5269 case Mips::FeatureMips32r5:
5270 selectArch("mips32r5");
5271 getTargetStreamer().emitDirectiveSetMips32R5();
5272 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005273 case Mips::FeatureMips32r6:
5274 selectArch("mips32r6");
5275 getTargetStreamer().emitDirectiveSetMips32R6();
5276 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005277 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005278 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00005279 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005280 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005281 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005282 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005283 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005284 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005285 case Mips::FeatureMips64r3:
5286 selectArch("mips64r3");
5287 getTargetStreamer().emitDirectiveSetMips64R3();
5288 break;
5289 case Mips::FeatureMips64r5:
5290 selectArch("mips64r5");
5291 getTargetStreamer().emitDirectiveSetMips64R5();
5292 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005293 case Mips::FeatureMips64r6:
5294 selectArch("mips64r6");
5295 getTargetStreamer().emitDirectiveSetMips64R6();
5296 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005297 }
5298 return false;
5299}
5300
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005301bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005302 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005303 if (getLexer().isNot(AsmToken::Comma)) {
5304 SMLoc Loc = getLexer().getLoc();
5305 Parser.eatToEndOfStatement();
5306 return Error(Loc, ErrorStr);
5307 }
5308
Matheus Almeida2852af82014-04-22 10:15:54 +00005309 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005310 return true;
5311}
5312
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005313// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
5314// In this class, it is only used for .cprestore.
5315// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
5316// MipsTargetELFStreamer and MipsAsmParser.
5317bool MipsAsmParser::isPicAndNotNxxAbi() {
5318 return inPicMode() && !(isABI_N32() || isABI_N64());
5319}
5320
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005321bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00005322 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00005323 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005324
Toma Tabacudde4c462014-11-06 10:02:45 +00005325 if (inMips16Mode()) {
5326 reportParseError(".cpload is not supported in Mips16 mode");
5327 return false;
5328 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005329
David Blaikie960ea3f2014-06-08 16:18:35 +00005330 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00005331 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005332 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5333 reportParseError("expected register containing function address");
5334 return false;
5335 }
5336
David Blaikie960ea3f2014-06-08 16:18:35 +00005337 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
5338 if (!RegOpnd.isGPRAsmReg()) {
5339 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005340 return false;
5341 }
5342
Toma Tabacudde4c462014-11-06 10:02:45 +00005343 // If this is not the end of the statement, report an error.
5344 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5345 reportParseError("unexpected token, expected end of statement");
5346 return false;
5347 }
5348
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005349 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005350 return false;
5351}
5352
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005353bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
5354 MCAsmParser &Parser = getParser();
5355
5356 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
5357 // is used in non-PIC mode.
5358
5359 if (inMips16Mode()) {
5360 reportParseError(".cprestore is not supported in Mips16 mode");
5361 return false;
5362 }
5363
5364 // Get the stack offset value.
5365 const MCExpr *StackOffset;
5366 int64_t StackOffsetVal;
5367 if (Parser.parseExpression(StackOffset)) {
5368 reportParseError("expected stack offset value");
5369 return false;
5370 }
5371
5372 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
5373 reportParseError("stack offset is not an absolute expression");
5374 return false;
5375 }
5376
5377 if (StackOffsetVal < 0) {
5378 Warning(Loc, ".cprestore with negative stack offset has no effect");
5379 IsCpRestoreSet = false;
5380 } else {
5381 IsCpRestoreSet = true;
5382 CpRestoreOffset = StackOffsetVal;
5383 }
5384
5385 // If this is not the end of the statement, report an error.
5386 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5387 reportParseError("unexpected token, expected end of statement");
5388 return false;
5389 }
5390
5391 // Store the $gp on the stack.
5392 SmallVector<MCInst, 3> StoreInsts;
5393 createCpRestoreMemOp(false /*IsLoad*/, CpRestoreOffset /*StackOffset*/, Loc,
5394 StoreInsts);
5395
5396 getTargetStreamer().emitDirectiveCpRestore(StoreInsts, CpRestoreOffset);
5397 Parser.Lex(); // Consume the EndOfStatement.
5398 return false;
5399}
5400
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005401bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005402 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005403 unsigned FuncReg;
5404 unsigned Save;
5405 bool SaveIsReg = true;
5406
Matheus Almeida7e815762014-06-18 13:08:59 +00005407 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005408 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005409 if (ResTy == MatchOperand_NoMatch) {
5410 reportParseError("expected register containing function address");
5411 Parser.eatToEndOfStatement();
5412 return false;
5413 }
5414
5415 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5416 if (!FuncRegOpnd.isGPRAsmReg()) {
5417 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
5418 Parser.eatToEndOfStatement();
5419 return false;
5420 }
5421
5422 FuncReg = FuncRegOpnd.getGPR32Reg();
5423 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005424
Toma Tabacu65f10572014-09-16 15:00:52 +00005425 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005426 return true;
5427
Toma Tabacu13964452014-09-04 13:23:44 +00005428 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005429 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00005430 const MCExpr *OffsetExpr;
5431 int64_t OffsetVal;
5432 SMLoc ExprLoc = getLexer().getLoc();
5433
5434 if (Parser.parseExpression(OffsetExpr) ||
5435 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
5436 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00005437 Parser.eatToEndOfStatement();
5438 return false;
5439 }
Daniel Sanders5d796282015-09-21 09:26:55 +00005440
5441 Save = OffsetVal;
5442 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00005443 } else {
5444 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5445 if (!SaveOpnd.isGPRAsmReg()) {
5446 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
5447 Parser.eatToEndOfStatement();
5448 return false;
5449 }
5450 Save = SaveOpnd.getGPR32Reg();
5451 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005452
Toma Tabacu65f10572014-09-16 15:00:52 +00005453 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005454 return true;
5455
Toma Tabacu8874eac2015-02-18 13:46:53 +00005456 const MCExpr *Expr;
5457 if (Parser.parseExpression(Expr)) {
5458 reportParseError("expected expression");
5459 return false;
5460 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005461
Toma Tabacu8874eac2015-02-18 13:46:53 +00005462 if (Expr->getKind() != MCExpr::SymbolRef) {
5463 reportParseError("expected symbol");
5464 return false;
5465 }
5466 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
5467
Daniel Sandersf173dda2015-09-22 10:50:09 +00005468 CpSaveLocation = Save;
5469 CpSaveLocationIsRegister = SaveIsReg;
5470
Toma Tabacu8874eac2015-02-18 13:46:53 +00005471 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
5472 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005473 return false;
5474}
5475
Daniel Sandersf173dda2015-09-22 10:50:09 +00005476bool MipsAsmParser::parseDirectiveCPReturn() {
5477 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
5478 CpSaveLocationIsRegister);
5479 return false;
5480}
5481
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005482bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005483 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005484 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5485 const AsmToken &Tok = Parser.getTok();
5486
5487 if (Tok.getString() == "2008") {
5488 Parser.Lex();
5489 getTargetStreamer().emitDirectiveNaN2008();
5490 return false;
5491 } else if (Tok.getString() == "legacy") {
5492 Parser.Lex();
5493 getTargetStreamer().emitDirectiveNaNLegacy();
5494 return false;
5495 }
5496 }
5497 // If we don't recognize the option passed to the .nan
5498 // directive (e.g. no option or unknown option), emit an error.
5499 reportParseError("invalid option in .nan directive");
5500 return false;
5501}
5502
Jack Carter0b744b32012-10-04 02:29:46 +00005503bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005504 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005505 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00005506 const AsmToken &Tok = Parser.getTok();
5507
5508 if (Tok.getString() == "noat") {
5509 return parseSetNoAtDirective();
5510 } else if (Tok.getString() == "at") {
5511 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00005512 } else if (Tok.getString() == "arch") {
5513 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005514 } else if (Tok.getString() == "fp") {
5515 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005516 } else if (Tok.getString() == "oddspreg") {
5517 return parseSetOddSPRegDirective();
5518 } else if (Tok.getString() == "nooddspreg") {
5519 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005520 } else if (Tok.getString() == "pop") {
5521 return parseSetPopDirective();
5522 } else if (Tok.getString() == "push") {
5523 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00005524 } else if (Tok.getString() == "reorder") {
5525 return parseSetReorderDirective();
5526 } else if (Tok.getString() == "noreorder") {
5527 return parseSetNoReorderDirective();
5528 } else if (Tok.getString() == "macro") {
5529 return parseSetMacroDirective();
5530 } else if (Tok.getString() == "nomacro") {
5531 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00005532 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00005533 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005534 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00005535 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005536 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00005537 getTargetStreamer().emitDirectiveSetNoMicroMips();
5538 Parser.eatToEndOfStatement();
5539 return false;
5540 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005541 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00005542 } else if (Tok.getString() == "mips0") {
5543 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00005544 } else if (Tok.getString() == "mips1") {
5545 return parseSetFeature(Mips::FeatureMips1);
5546 } else if (Tok.getString() == "mips2") {
5547 return parseSetFeature(Mips::FeatureMips2);
5548 } else if (Tok.getString() == "mips3") {
5549 return parseSetFeature(Mips::FeatureMips3);
5550 } else if (Tok.getString() == "mips4") {
5551 return parseSetFeature(Mips::FeatureMips4);
5552 } else if (Tok.getString() == "mips5") {
5553 return parseSetFeature(Mips::FeatureMips5);
5554 } else if (Tok.getString() == "mips32") {
5555 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00005556 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005557 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005558 } else if (Tok.getString() == "mips32r3") {
5559 return parseSetFeature(Mips::FeatureMips32r3);
5560 } else if (Tok.getString() == "mips32r5") {
5561 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005562 } else if (Tok.getString() == "mips32r6") {
5563 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005564 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005565 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005566 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005567 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005568 } else if (Tok.getString() == "mips64r3") {
5569 return parseSetFeature(Mips::FeatureMips64r3);
5570 } else if (Tok.getString() == "mips64r5") {
5571 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005572 } else if (Tok.getString() == "mips64r6") {
5573 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00005574 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005575 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005576 } else if (Tok.getString() == "nodsp") {
5577 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00005578 } else if (Tok.getString() == "msa") {
5579 return parseSetMsaDirective();
5580 } else if (Tok.getString() == "nomsa") {
5581 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00005582 } else if (Tok.getString() == "softfloat") {
5583 return parseSetSoftFloatDirective();
5584 } else if (Tok.getString() == "hardfloat") {
5585 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00005586 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00005587 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00005588 parseSetAssignment();
5589 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005590 }
Jack Carter07c818d2013-01-25 01:31:34 +00005591
Jack Carter0b744b32012-10-04 02:29:46 +00005592 return true;
5593}
5594
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005595/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00005596/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005597bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005598 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005599 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5600 for (;;) {
5601 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005602 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00005603 return true;
5604
5605 getParser().getStreamer().EmitValue(Value, Size);
5606
5607 if (getLexer().is(AsmToken::EndOfStatement))
5608 break;
5609
Jack Carter07c818d2013-01-25 01:31:34 +00005610 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005611 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00005612 Parser.Lex();
5613 }
5614 }
5615
5616 Parser.Lex();
5617 return false;
5618}
5619
Vladimir Medic4c299852013-11-06 11:27:05 +00005620/// parseDirectiveGpWord
5621/// ::= .gpword local_sym
5622bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005623 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00005624 const MCExpr *Value;
5625 // EmitGPRel32Value requires an expression, so we are using base class
5626 // method to evaluate the expression.
5627 if (getParser().parseExpression(Value))
5628 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00005629 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00005630
Vladimir Medice10c1122013-11-13 13:18:04 +00005631 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005632 return Error(getLexer().getLoc(),
5633 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00005634 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00005635 return false;
5636}
5637
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005638/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00005639/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005640bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005641 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005642 const MCExpr *Value;
5643 // EmitGPRel64Value requires an expression, so we are using base class
5644 // method to evaluate the expression.
5645 if (getParser().parseExpression(Value))
5646 return true;
5647 getParser().getStreamer().EmitGPRel64Value(Value);
5648
5649 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005650 return Error(getLexer().getLoc(),
5651 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00005652 Parser.Lex(); // Eat EndOfStatement token.
5653 return false;
5654}
5655
Jack Carter0cd3c192014-01-06 23:27:31 +00005656bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005657 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00005658 // Get the option token.
5659 AsmToken Tok = Parser.getTok();
5660 // At the moment only identifiers are supported.
5661 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005662 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00005663 Parser.eatToEndOfStatement();
5664 return false;
5665 }
5666
5667 StringRef Option = Tok.getIdentifier();
5668
5669 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005670 // MipsAsmParser needs to know if the current PIC mode changes.
5671 IsPicEnabled = false;
5672
Jack Carter0cd3c192014-01-06 23:27:31 +00005673 getTargetStreamer().emitDirectiveOptionPic0();
5674 Parser.Lex();
5675 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5676 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005677 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005678 Parser.eatToEndOfStatement();
5679 }
5680 return false;
5681 }
5682
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005683 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005684 // MipsAsmParser needs to know if the current PIC mode changes.
5685 IsPicEnabled = true;
5686
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005687 getTargetStreamer().emitDirectiveOptionPic2();
5688 Parser.Lex();
5689 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5690 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005691 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005692 Parser.eatToEndOfStatement();
5693 }
5694 return false;
5695 }
5696
Jack Carter0cd3c192014-01-06 23:27:31 +00005697 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00005698 Warning(Parser.getTok().getLoc(),
5699 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00005700 Parser.eatToEndOfStatement();
5701 return false;
5702}
5703
Toma Tabacu9ca50962015-04-16 09:53:47 +00005704/// parseInsnDirective
5705/// ::= .insn
5706bool MipsAsmParser::parseInsnDirective() {
5707 // If this is not the end of the statement, report an error.
5708 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5709 reportParseError("unexpected token, expected end of statement");
5710 return false;
5711 }
5712
5713 // The actual label marking happens in
5714 // MipsELFStreamer::createPendingLabelRelocs().
5715 getTargetStreamer().emitDirectiveInsn();
5716
5717 getParser().Lex(); // Eat EndOfStatement token.
5718 return false;
5719}
5720
Daniel Sanders7e527422014-07-10 13:38:23 +00005721/// parseDirectiveModule
5722/// ::= .module oddspreg
5723/// ::= .module nooddspreg
5724/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00005725/// ::= .module softfloat
5726/// ::= .module hardfloat
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005727bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005728 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005729 MCAsmLexer &Lexer = getLexer();
5730 SMLoc L = Lexer.getLoc();
5731
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00005732 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005733 // TODO : get a better message.
5734 reportParseError(".module directive must appear before any code");
5735 return false;
5736 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005737
Toma Tabacuc405c822015-01-23 10:40:19 +00005738 StringRef Option;
5739 if (Parser.parseIdentifier(Option)) {
5740 reportParseError("expected .module option identifier");
5741 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005742 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005743
Toma Tabacuc405c822015-01-23 10:40:19 +00005744 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005745 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005746
Toma Tabacu3c499582015-06-25 10:56:57 +00005747 // Synchronize the abiflags information with the FeatureBits information we
5748 // changed above.
5749 getTargetStreamer().updateABIInfo(*this);
5750
5751 // If printing assembly, use the recently updated abiflags information.
5752 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5753 // emitted at the end).
5754 getTargetStreamer().emitDirectiveModuleOddSPReg();
5755
Toma Tabacuc405c822015-01-23 10:40:19 +00005756 // If this is not the end of the statement, report an error.
5757 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5758 reportParseError("unexpected token, expected end of statement");
5759 return false;
5760 }
5761
5762 return false; // parseDirectiveModule has finished successfully.
5763 } else if (Option == "nooddspreg") {
5764 if (!isABI_O32()) {
5765 Error(L, "'.module nooddspreg' requires the O32 ABI");
5766 return false;
5767 }
5768
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005769 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005770
Toma Tabacu3c499582015-06-25 10:56:57 +00005771 // Synchronize the abiflags information with the FeatureBits information we
5772 // changed above.
5773 getTargetStreamer().updateABIInfo(*this);
5774
5775 // If printing assembly, use the recently updated abiflags information.
5776 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5777 // emitted at the end).
5778 getTargetStreamer().emitDirectiveModuleOddSPReg();
5779
Toma Tabacuc405c822015-01-23 10:40:19 +00005780 // If this is not the end of the statement, report an error.
5781 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5782 reportParseError("unexpected token, expected end of statement");
5783 return false;
5784 }
5785
5786 return false; // parseDirectiveModule has finished successfully.
5787 } else if (Option == "fp") {
5788 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00005789 } else if (Option == "softfloat") {
5790 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5791
5792 // Synchronize the ABI Flags information with the FeatureBits information we
5793 // updated above.
5794 getTargetStreamer().updateABIInfo(*this);
5795
5796 // If printing assembly, use the recently updated ABI Flags information.
5797 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5798 // emitted later).
5799 getTargetStreamer().emitDirectiveModuleSoftFloat();
5800
5801 // If this is not the end of the statement, report an error.
5802 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5803 reportParseError("unexpected token, expected end of statement");
5804 return false;
5805 }
5806
5807 return false; // parseDirectiveModule has finished successfully.
5808 } else if (Option == "hardfloat") {
5809 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5810
5811 // Synchronize the ABI Flags information with the FeatureBits information we
5812 // updated above.
5813 getTargetStreamer().updateABIInfo(*this);
5814
5815 // If printing assembly, use the recently updated ABI Flags information.
5816 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5817 // emitted later).
5818 getTargetStreamer().emitDirectiveModuleHardFloat();
5819
5820 // If this is not the end of the statement, report an error.
5821 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5822 reportParseError("unexpected token, expected end of statement");
5823 return false;
5824 }
5825
5826 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00005827 } else {
5828 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
5829 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005830}
5831
5832/// parseDirectiveModuleFP
5833/// ::= =32
5834/// ::= =xx
5835/// ::= =64
5836bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005837 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005838 MCAsmLexer &Lexer = getLexer();
5839
5840 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005841 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005842 return false;
5843 }
5844 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005845
Daniel Sanders7e527422014-07-10 13:38:23 +00005846 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005847 if (!parseFpABIValue(FpABI, ".module"))
5848 return false;
5849
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005850 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005851 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005852 return false;
5853 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005854
Toma Tabacua64e5402015-06-25 12:44:38 +00005855 // Synchronize the abiflags information with the FeatureBits information we
5856 // changed above.
5857 getTargetStreamer().updateABIInfo(*this);
5858
5859 // If printing assembly, use the recently updated abiflags information.
5860 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5861 // emitted at the end).
5862 getTargetStreamer().emitDirectiveModuleFP();
5863
Daniel Sanders7e527422014-07-10 13:38:23 +00005864 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005865 return false;
5866}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005867
Daniel Sanders7e527422014-07-10 13:38:23 +00005868bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005869 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005870 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005871 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005872 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005873
5874 if (Lexer.is(AsmToken::Identifier)) {
5875 StringRef Value = Parser.getTok().getString();
5876 Parser.Lex();
5877
5878 if (Value != "xx") {
5879 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5880 return false;
5881 }
5882
5883 if (!isABI_O32()) {
5884 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
5885 return false;
5886 }
5887
Daniel Sanders7e527422014-07-10 13:38:23 +00005888 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005889 if (ModuleLevelOptions) {
5890 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5891 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5892 } else {
5893 setFeatureBits(Mips::FeatureFPXX, "fpxx");
5894 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5895 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005896 return true;
5897 }
5898
5899 if (Lexer.is(AsmToken::Integer)) {
5900 unsigned Value = Parser.getTok().getIntVal();
5901 Parser.Lex();
5902
5903 if (Value != 32 && Value != 64) {
5904 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5905 return false;
5906 }
5907
5908 if (Value == 32) {
5909 if (!isABI_O32()) {
5910 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
5911 return false;
5912 }
5913
Daniel Sanders7e527422014-07-10 13:38:23 +00005914 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005915 if (ModuleLevelOptions) {
5916 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5917 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5918 } else {
5919 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
5920 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5921 }
Toma Tabacua64e5402015-06-25 12:44:38 +00005922 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00005923 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005924 if (ModuleLevelOptions) {
5925 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5926 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5927 } else {
5928 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
5929 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
5930 }
Toma Tabacua64e5402015-06-25 12:44:38 +00005931 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005932
Daniel Sanders7e527422014-07-10 13:38:23 +00005933 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005934 }
5935
5936 return false;
5937}
5938
Jack Carter0b744b32012-10-04 02:29:46 +00005939bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005940 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005941 StringRef IDVal = DirectiveID.getString();
5942
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005943 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005944 return parseDirectiveCpLoad(DirectiveID.getLoc());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005945 if (IDVal == ".cprestore")
5946 return parseDirectiveCpRestore(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00005947 if (IDVal == ".dword") {
5948 parseDataDirective(8, DirectiveID.getLoc());
5949 return false;
5950 }
Jack Carterd0bd6422013-04-18 00:41:53 +00005951 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005952 StringRef SymbolName;
5953
5954 if (Parser.parseIdentifier(SymbolName)) {
5955 reportParseError("expected identifier after .ent");
5956 return false;
5957 }
5958
5959 // There's an undocumented extension that allows an integer to
5960 // follow the name of the procedure which AFAICS is ignored by GAS.
5961 // Example: .ent foo,2
5962 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5963 if (getLexer().isNot(AsmToken::Comma)) {
5964 // Even though we accept this undocumented extension for compatibility
5965 // reasons, the additional integer argument does not actually change
5966 // the behaviour of the '.ent' directive, so we would like to discourage
5967 // its use. We do this by not referring to the extended version in
5968 // error messages which are not directly related to its use.
5969 reportParseError("unexpected token, expected end of statement");
5970 return false;
5971 }
5972 Parser.Lex(); // Eat the comma.
5973 const MCExpr *DummyNumber;
5974 int64_t DummyNumberVal;
5975 // If the user was explicitly trying to use the extended version,
5976 // we still give helpful extension-related error messages.
5977 if (Parser.parseExpression(DummyNumber)) {
5978 reportParseError("expected number after comma");
5979 return false;
5980 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00005981 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005982 reportParseError("expected an absolute expression after comma");
5983 return false;
5984 }
5985 }
5986
5987 // If this is not the end of the statement, report an error.
5988 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5989 reportParseError("unexpected token, expected end of statement");
5990 return false;
5991 }
5992
Jim Grosbach6f482002015-05-18 18:43:14 +00005993 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005994
5995 getTargetStreamer().emitDirectiveEnt(*Sym);
5996 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005997 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00005998 return false;
5999 }
6000
Jack Carter07c818d2013-01-25 01:31:34 +00006001 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006002 StringRef SymbolName;
6003
6004 if (Parser.parseIdentifier(SymbolName)) {
6005 reportParseError("expected identifier after .end");
6006 return false;
6007 }
6008
6009 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6010 reportParseError("unexpected token, expected end of statement");
6011 return false;
6012 }
6013
6014 if (CurrentFn == nullptr) {
6015 reportParseError(".end used without .ent");
6016 return false;
6017 }
6018
6019 if ((SymbolName != CurrentFn->getName())) {
6020 reportParseError(".end symbol does not match .ent symbol");
6021 return false;
6022 }
6023
6024 getTargetStreamer().emitDirectiveEnd(SymbolName);
6025 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006026 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006027 return false;
6028 }
6029
Jack Carter07c818d2013-01-25 01:31:34 +00006030 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006031 // .frame $stack_reg, frame_size_in_bytes, $return_reg
6032 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00006033 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006034 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6035 reportParseError("expected stack register");
6036 return false;
6037 }
6038
6039 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6040 if (!StackRegOpnd.isGPRAsmReg()) {
6041 reportParseError(StackRegOpnd.getStartLoc(),
6042 "expected general purpose register");
6043 return false;
6044 }
6045 unsigned StackReg = StackRegOpnd.getGPR32Reg();
6046
6047 if (Parser.getTok().is(AsmToken::Comma))
6048 Parser.Lex();
6049 else {
6050 reportParseError("unexpected token, expected comma");
6051 return false;
6052 }
6053
6054 // Parse the frame size.
6055 const MCExpr *FrameSize;
6056 int64_t FrameSizeVal;
6057
6058 if (Parser.parseExpression(FrameSize)) {
6059 reportParseError("expected frame size value");
6060 return false;
6061 }
6062
Jim Grosbach13760bd2015-05-30 01:25:56 +00006063 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006064 reportParseError("frame size not an absolute expression");
6065 return false;
6066 }
6067
6068 if (Parser.getTok().is(AsmToken::Comma))
6069 Parser.Lex();
6070 else {
6071 reportParseError("unexpected token, expected comma");
6072 return false;
6073 }
6074
6075 // Parse the return register.
6076 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00006077 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006078 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6079 reportParseError("expected return register");
6080 return false;
6081 }
6082
6083 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6084 if (!ReturnRegOpnd.isGPRAsmReg()) {
6085 reportParseError(ReturnRegOpnd.getStartLoc(),
6086 "expected general purpose register");
6087 return false;
6088 }
6089
6090 // If this is not the end of the statement, report an error.
6091 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6092 reportParseError("unexpected token, expected end of statement");
6093 return false;
6094 }
6095
6096 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
6097 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006098 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006099 return false;
6100 }
6101
Jack Carter07c818d2013-01-25 01:31:34 +00006102 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00006103 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00006104 }
6105
Daniel Sandersd97a6342014-08-13 10:07:34 +00006106 if (IDVal == ".mask" || IDVal == ".fmask") {
6107 // .mask bitmask, frame_offset
6108 // bitmask: One bit for each register used.
6109 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
6110 // first register is expected to be saved.
6111 // Examples:
6112 // .mask 0x80000000, -4
6113 // .fmask 0x80000000, -4
6114 //
Jack Carterbe332172012-09-07 00:48:02 +00006115
Daniel Sandersd97a6342014-08-13 10:07:34 +00006116 // Parse the bitmask
6117 const MCExpr *BitMask;
6118 int64_t BitMaskVal;
6119
6120 if (Parser.parseExpression(BitMask)) {
6121 reportParseError("expected bitmask value");
6122 return false;
6123 }
6124
Jim Grosbach13760bd2015-05-30 01:25:56 +00006125 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006126 reportParseError("bitmask not an absolute expression");
6127 return false;
6128 }
6129
6130 if (Parser.getTok().is(AsmToken::Comma))
6131 Parser.Lex();
6132 else {
6133 reportParseError("unexpected token, expected comma");
6134 return false;
6135 }
6136
6137 // Parse the frame_offset
6138 const MCExpr *FrameOffset;
6139 int64_t FrameOffsetVal;
6140
6141 if (Parser.parseExpression(FrameOffset)) {
6142 reportParseError("expected frame offset value");
6143 return false;
6144 }
6145
Jim Grosbach13760bd2015-05-30 01:25:56 +00006146 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006147 reportParseError("frame offset not an absolute expression");
6148 return false;
6149 }
6150
6151 // If this is not the end of the statement, report an error.
6152 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6153 reportParseError("unexpected token, expected end of statement");
6154 return false;
6155 }
6156
6157 if (IDVal == ".mask")
6158 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
6159 else
6160 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00006161 return false;
6162 }
6163
Matheus Almeida0051f2d2014-04-16 15:48:55 +00006164 if (IDVal == ".nan")
6165 return parseDirectiveNaN();
6166
Jack Carter07c818d2013-01-25 01:31:34 +00006167 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00006168 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00006169 return false;
6170 }
6171
Rafael Espindolab59fb732014-03-28 18:50:26 +00006172 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00006173 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00006174 return false;
6175 }
6176
Jack Carter07c818d2013-01-25 01:31:34 +00006177 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00006178 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00006179 return false;
6180 }
6181
Jack Carter0cd3c192014-01-06 23:27:31 +00006182 if (IDVal == ".option")
6183 return parseDirectiveOption();
6184
6185 if (IDVal == ".abicalls") {
6186 getTargetStreamer().emitDirectiveAbiCalls();
6187 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006188 Error(Parser.getTok().getLoc(),
6189 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00006190 // Clear line
6191 Parser.eatToEndOfStatement();
6192 }
6193 return false;
6194 }
6195
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006196 if (IDVal == ".cpsetup")
6197 return parseDirectiveCPSetup();
6198
Daniel Sandersf173dda2015-09-22 10:50:09 +00006199 if (IDVal == ".cpreturn")
6200 return parseDirectiveCPReturn();
6201
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006202 if (IDVal == ".module")
6203 return parseDirectiveModule();
6204
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00006205 if (IDVal == ".llvm_internal_mips_reallow_module_directive")
6206 return parseInternalDirectiveReallowModule();
6207
Toma Tabacu9ca50962015-04-16 09:53:47 +00006208 if (IDVal == ".insn")
6209 return parseInsnDirective();
6210
Rafael Espindola870c4e92012-01-11 03:56:41 +00006211 return true;
6212}
6213
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00006214bool MipsAsmParser::parseInternalDirectiveReallowModule() {
6215 // If this is not the end of the statement, report an error.
6216 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6217 reportParseError("unexpected token, expected end of statement");
6218 return false;
6219 }
6220
6221 getTargetStreamer().reallowModuleDirective();
6222
6223 getParser().Lex(); // Eat EndOfStatement token.
6224 return false;
6225}
6226
Rafael Espindola870c4e92012-01-11 03:56:41 +00006227extern "C" void LLVMInitializeMipsAsmParser() {
6228 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
6229 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
6230 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
6231 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
6232}
Jack Carterb4dbc172012-09-05 23:34:03 +00006233
6234#define GET_REGISTER_MATCHER
6235#define GET_MATCHER_IMPLEMENTATION
6236#include "MipsGenAsmMatcher.inc"