blob: cc54f1d57f6f482442a15c104f9d853161efdf51 [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"
Simon Atanasyanbe186202016-02-11 06:45:54 +000026#include "llvm/MC/MCSectionELF.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000027#include "llvm/MC/MCStreamer.h"
28#include "llvm/MC/MCSubtargetInfo.h"
29#include "llvm/MC/MCSymbol.h"
Daniel Sandersb50ccf82014-04-01 10:35:28 +000030#include "llvm/Support/Debug.h"
Simon Atanasyanbe186202016-02-11 06:45:54 +000031#include "llvm/Support/ELF.h"
Matheus Almeidae0d75aa2013-12-13 11:11:02 +000032#include "llvm/Support/MathExtras.h"
Daniel Sandersef638fe2014-10-03 15:37:37 +000033#include "llvm/Support/SourceMgr.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000034#include "llvm/Support/TargetRegistry.h"
Benjamin Kramer799003b2015-03-23 19:32:43 +000035#include "llvm/Support/raw_ostream.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000036#include <memory>
Rafael Espindola870c4e92012-01-11 03:56:41 +000037
38using namespace llvm;
39
Chandler Carruthe96dd892014-04-21 22:55:11 +000040#define DEBUG_TYPE "mips-asm-parser"
41
Joey Gouly0e76fa72013-09-12 10:28:05 +000042namespace llvm {
43class MCInstrInfo;
44}
45
Rafael Espindola870c4e92012-01-11 03:56:41 +000046namespace {
Jack Carter0b744b32012-10-04 02:29:46 +000047class MipsAssemblerOptions {
48public:
Toma Tabacu465acfd2015-06-09 13:33:26 +000049 MipsAssemblerOptions(const FeatureBitset &Features_) :
Toma Tabacu9db22db2014-09-09 10:15:38 +000050 ATReg(1), Reorder(true), Macro(true), Features(Features_) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000051
Toma Tabacu9db22db2014-09-09 10:15:38 +000052 MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
Toma Tabacub19cf202015-04-27 13:12:59 +000053 ATReg = Opts->getATRegIndex();
Toma Tabacu9db22db2014-09-09 10:15:38 +000054 Reorder = Opts->isReorder();
55 Macro = Opts->isMacro();
56 Features = Opts->getFeatures();
57 }
58
Toma Tabacub19cf202015-04-27 13:12:59 +000059 unsigned getATRegIndex() const { return ATReg; }
60 bool setATRegIndex(unsigned Reg) {
Toma Tabacu92dbbf12015-03-26 13:08:55 +000061 if (Reg > 31)
62 return false;
63
64 ATReg = Reg;
65 return true;
66 }
Jack Carter0b744b32012-10-04 02:29:46 +000067
Toma Tabacu9db22db2014-09-09 10:15:38 +000068 bool isReorder() const { return Reorder; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000069 void setReorder() { Reorder = true; }
70 void setNoReorder() { Reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000071
Toma Tabacu9db22db2014-09-09 10:15:38 +000072 bool isMacro() const { return Macro; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000073 void setMacro() { Macro = true; }
74 void setNoMacro() { Macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000075
Toma Tabacu465acfd2015-06-09 13:33:26 +000076 const FeatureBitset &getFeatures() const { return Features; }
77 void setFeatures(const FeatureBitset &Features_) { Features = Features_; }
Toma Tabacu9db22db2014-09-09 10:15:38 +000078
Daniel Sandersf0df2212014-08-04 12:20:00 +000079 // Set of features that are either architecture features or referenced
80 // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6).
81 // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
82 // The reason we need this mask is explained in the selectArch function.
83 // FIXME: Ideally we would like TableGen to generate this information.
Michael Kupersteindb0712f2015-05-26 10:47:10 +000084 static const FeatureBitset AllArchRelatedMask;
Daniel Sandersf0df2212014-08-04 12:20:00 +000085
Jack Carter0b744b32012-10-04 02:29:46 +000086private:
Toma Tabacu3c24b042014-09-05 15:43:21 +000087 unsigned ATReg;
88 bool Reorder;
89 bool Macro;
Toma Tabacu465acfd2015-06-09 13:33:26 +000090 FeatureBitset Features;
Jack Carter0b744b32012-10-04 02:29:46 +000091};
92}
93
Michael Kupersteindb0712f2015-05-26 10:47:10 +000094const FeatureBitset MipsAssemblerOptions::AllArchRelatedMask = {
95 Mips::FeatureMips1, Mips::FeatureMips2, Mips::FeatureMips3,
96 Mips::FeatureMips3_32, Mips::FeatureMips3_32r2, Mips::FeatureMips4,
97 Mips::FeatureMips4_32, Mips::FeatureMips4_32r2, Mips::FeatureMips5,
98 Mips::FeatureMips5_32r2, Mips::FeatureMips32, Mips::FeatureMips32r2,
99 Mips::FeatureMips32r3, Mips::FeatureMips32r5, Mips::FeatureMips32r6,
100 Mips::FeatureMips64, Mips::FeatureMips64r2, Mips::FeatureMips64r3,
101 Mips::FeatureMips64r5, Mips::FeatureMips64r6, Mips::FeatureCnMips,
102 Mips::FeatureFP64Bit, Mips::FeatureGP64Bit, Mips::FeatureNaN2008
103};
104
Jack Carter0b744b32012-10-04 02:29:46 +0000105namespace {
Rafael Espindola870c4e92012-01-11 03:56:41 +0000106class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000107 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola961d4692014-11-11 05:18:41 +0000108 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000109 return static_cast<MipsTargetStreamer &>(TS);
110 }
111
Eric Christophera5762812015-01-26 17:33:46 +0000112 MipsABIInfo ABI;
Toma Tabacu9db22db2014-09-09 10:15:38 +0000113 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
Daniel Sandersd97a6342014-08-13 10:07:34 +0000114 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
115 // nullptr, which indicates that no function is currently
116 // selected. This usually happens after an '.end func'
117 // directive.
Toma Tabacud88d79c2015-06-23 14:39:42 +0000118 bool IsLittleEndian;
Daniel Sandersa6994442015-08-18 12:33:54 +0000119 bool IsPicEnabled;
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000120 bool IsCpRestoreSet;
121 int CpRestoreOffset;
Daniel Sandersf173dda2015-09-22 10:50:09 +0000122 unsigned CpSaveLocation;
123 /// If true, then CpSaveLocation is a register, otherwise it's an offset.
124 bool CpSaveLocationIsRegister;
Jack Carter0b744b32012-10-04 02:29:46 +0000125
Daniel Sandersef638fe2014-10-03 15:37:37 +0000126 // Print a warning along with its fix-it message at the given range.
127 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
128 SMRange Range, bool ShowColors = true);
129
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000130#define GET_ASSEMBLER_HEADER
131#include "MipsGenAsmMatcher.inc"
132
Matheus Almeida595fcab2014-06-11 15:05:56 +0000133 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
134
Chad Rosier49963552012-10-13 00:26:04 +0000135 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000136 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000137 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000138 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000139
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000140 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000141 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000142
Toma Tabacu13964452014-09-04 13:23:44 +0000143 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000144
Toma Tabacu13964452014-09-04 13:23:44 +0000145 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000146
David Blaikie960ea3f2014-06-08 16:18:35 +0000147 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
148 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000149
Craig Topper56c590a2014-04-29 07:58:02 +0000150 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000151
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000152 OperandMatchResultTy parseMemOperand(OperandVector &Operands);
153 OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000154 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000155 StringRef Identifier, SMLoc S);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000156 OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands,
157 SMLoc S);
158 OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
159 OperandMatchResultTy parseImm(OperandVector &Operands);
160 OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
161 OperandMatchResultTy parseInvNum(OperandVector &Operands);
162 OperandMatchResultTy parseLSAImm(OperandVector &Operands);
163 OperandMatchResultTy parseRegisterPair(OperandVector &Operands);
164 OperandMatchResultTy parseMovePRegPair(OperandVector &Operands);
165 OperandMatchResultTy parseRegisterList(OperandVector &Operands);
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000166
David Blaikie960ea3f2014-06-08 16:18:35 +0000167 bool searchSymbolAlias(OperandVector &Operands);
168
Toma Tabacu13964452014-09-04 13:23:44 +0000169 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000170
Daniel Sanders5bf6eab2015-10-26 23:50:00 +0000171 enum MacroExpanderResultTy {
172 MER_NotAMacro,
173 MER_Success,
174 MER_Fail,
175 };
Jack Carter30a59822012-10-04 04:03:53 +0000176
Matheus Almeida3813d572014-06-19 14:39:14 +0000177 // Expands assembly pseudo instructions.
Daniel Sanders5bf6eab2015-10-26 23:50:00 +0000178 MacroExpanderResultTy
179 tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
180 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000181
Toma Tabacu8f6603a2015-01-30 11:18:50 +0000182 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
183 SmallVectorImpl<MCInst> &Instructions);
184
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000185 bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000186 bool Is32BitImm, bool IsAddress, SMLoc IDLoc,
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000187 SmallVectorImpl<MCInst> &Instructions);
188
Toma Tabacuf712ede2015-06-17 14:31:51 +0000189 bool loadAndAddSymbolAddress(const MCExpr *SymExpr, unsigned DstReg,
190 unsigned SrcReg, bool Is32BitSym, SMLoc IDLoc,
191 SmallVectorImpl<MCInst> &Instructions);
Toma Tabacu674825c2015-06-16 12:16:24 +0000192
Toma Tabacu00e98672015-05-01 12:19:27 +0000193 bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000194 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000195
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000196 bool expandLoadAddress(unsigned DstReg, unsigned BaseReg,
197 const MCOperand &Offset, bool Is32BitAddress,
198 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000199
Jozef Kolek5cfebdd2015-01-21 12:39:30 +0000200 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
201 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000202
Jack Carter9e65aa32013-03-22 00:05:30 +0000203 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000204 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
205 bool isImmOpnd);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000206
207 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
208 SmallVectorImpl<MCInst> &Instructions);
209
Zoran Jovanoviccdb64562015-09-28 11:11:34 +0000210 bool expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
211 SmallVectorImpl<MCInst> &Instructions);
212
Toma Tabacue1e460d2015-06-11 10:36:10 +0000213 bool expandBranchImm(MCInst &Inst, SMLoc IDLoc,
214 SmallVectorImpl<MCInst> &Instructions);
215
Toma Tabacu1a108322015-06-17 13:20:24 +0000216 bool expandCondBranches(MCInst &Inst, SMLoc IDLoc,
217 SmallVectorImpl<MCInst> &Instructions);
218
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000219 bool expandDiv(MCInst &Inst, SMLoc IDLoc,
220 SmallVectorImpl<MCInst> &Instructions, const bool IsMips64,
221 const bool Signed);
222
Zoran Jovanovicd665a662016-02-22 16:00:23 +0000223 bool expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU, SMLoc IDLoc,
224 SmallVectorImpl<MCInst> &Instructions);
225
Daniel Sanders6394ee52015-10-15 14:52:58 +0000226 bool expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
227 SmallVectorImpl<MCInst> &Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000228
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +0000229 bool expandUlw(MCInst &Inst, SMLoc IDLoc,
230 SmallVectorImpl<MCInst> &Instructions);
231
Zoran Jovanovic00f998b2015-11-19 14:15:03 +0000232 bool expandRotation(MCInst &Inst, SMLoc IDLoc,
233 SmallVectorImpl<MCInst> &Instructions);
234 bool expandRotationImm(MCInst &Inst, SMLoc IDLoc,
235 SmallVectorImpl<MCInst> &Instructions);
236 bool expandDRotation(MCInst &Inst, SMLoc IDLoc,
237 SmallVectorImpl<MCInst> &Instructions);
238 bool expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
239 SmallVectorImpl<MCInst> &Instructions);
240
Zoran Jovanovicd474ef32016-01-29 16:18:34 +0000241 bool expandAbs(MCInst &Inst, SMLoc IDLoc,
242 SmallVectorImpl<MCInst> &Instructions);
243
Toma Tabacu234482a2015-03-16 12:03:39 +0000244 void createNop(bool hasShortDelaySlot, SMLoc IDLoc,
245 SmallVectorImpl<MCInst> &Instructions);
246
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000247 void createAddu(unsigned DstReg, unsigned SrcReg, unsigned TrgReg,
Toma Tabacu0b3e9782015-06-23 14:00:54 +0000248 bool Is64Bit, SmallVectorImpl<MCInst> &Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000249
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000250 void createCpRestoreMemOp(bool IsLoad, int StackOffset, SMLoc IDLoc,
251 SmallVectorImpl<MCInst> &Instructions);
252
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000253 bool reportParseError(Twine ErrorMsg);
254 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000255
Jack Carterb5cf5902013-04-17 00:18:04 +0000256 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000257 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000258
Vladimir Medic4c299852013-11-06 11:27:05 +0000259 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000260
261 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000262 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000263 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000264 bool parseSetFeature(uint64_t Feature);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000265 bool isPicAndNotNxxAbi(); // Used by .cpload, .cprestore, and .cpsetup.
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000266 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000267 bool parseDirectiveCpRestore(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000268 bool parseDirectiveCPSetup();
Daniel Sandersf173dda2015-09-22 10:50:09 +0000269 bool parseDirectiveCPReturn();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000270 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000271 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000272 bool parseDirectiveOption();
Toma Tabacu9ca50962015-04-16 09:53:47 +0000273 bool parseInsnDirective();
Simon Atanasyanbe186202016-02-11 06:45:54 +0000274 bool parseSSectionDirective(StringRef Section, unsigned Type);
Jack Carter0b744b32012-10-04 02:29:46 +0000275
276 bool parseSetAtDirective();
277 bool parseSetNoAtDirective();
278 bool parseSetMacroDirective();
279 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000280 bool parseSetMsaDirective();
281 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000282 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000283 bool parseSetReorderDirective();
284 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000285 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000286 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000287 bool parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +0000288 bool parseSetOddSPRegDirective();
289 bool parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000290 bool parseSetPopDirective();
291 bool parseSetPushDirective();
Toma Tabacu29696502015-06-02 09:48:04 +0000292 bool parseSetSoftFloatDirective();
293 bool parseSetHardFloatDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000294
Jack Carterd76b2372013-03-21 21:44:16 +0000295 bool parseSetAssignment();
296
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000297 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000298 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000299 bool parseDirectiveGpDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000300 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000301 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000302 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
303 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000304
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000305 bool parseInternalDirectiveReallowModule();
306
Jack Carterdc1e35d2012-09-06 20:00:02 +0000307 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000308
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000309 bool eatComma(StringRef ErrorStr);
310
Jack Carter1ac53222013-02-20 23:11:17 +0000311 int matchCPURegisterName(StringRef Symbol);
312
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000313 int matchHWRegsRegisterName(StringRef Symbol);
314
Jack Carter873c7242013-01-12 01:03:14 +0000315 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000316
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000317 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000318
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000319 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000320
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000321 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000322
Jack Carter5dc8ac92013-09-25 23:50:44 +0000323 int matchMSA128RegisterName(StringRef Name);
324
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000325 int matchMSA128CtrlRegisterName(StringRef Name);
326
Jack Carterd0bd6422013-04-18 00:41:53 +0000327 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000328
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000329 unsigned getGPR(int RegNo);
330
Toma Tabacu89a712b2015-04-15 10:48:56 +0000331 /// Returns the internal register number for the current AT. Also checks if
332 /// the current AT is unavailable (set to $0) and gives an error if it is.
333 /// This should be used in pseudo-instruction expansions which need AT.
334 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000335
336 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000337 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000338
339 // Helper function that checks if the value of a vector index is within the
340 // boundaries of accepted values for each RegisterKind
341 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
342 bool validateMSAIndex(int Val, int RegKind);
343
Daniel Sandersf0df2212014-08-04 12:20:00 +0000344 // Selects a new architecture by updating the FeatureBits with the necessary
345 // info including implied dependencies.
346 // Internally, it clears all the feature bits related to *any* architecture
347 // and selects the new one using the ToggleFeature functionality of the
348 // MCSubtargetInfo object that handles implied dependencies. The reason we
349 // clear all the arch related bits manually is because ToggleFeature only
350 // clears the features that imply the feature being cleared and not the
351 // features implied by the feature being cleared. This is easier to see
352 // with an example:
353 // --------------------------------------------------
354 // | Feature | Implies |
355 // | -------------------------------------------------|
356 // | FeatureMips1 | None |
357 // | FeatureMips2 | FeatureMips1 |
358 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
359 // | FeatureMips4 | FeatureMips3 |
360 // | ... | |
361 // --------------------------------------------------
362 //
363 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
364 // FeatureMipsGP64 | FeatureMips1)
365 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
366 void selectArch(StringRef ArchFeature) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000367 MCSubtargetInfo &STI = copySTI();
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000368 FeatureBitset FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000369 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
370 STI.setFeatureBits(FeatureBits);
371 setAvailableFeatures(
372 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000373 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000374 }
375
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000376 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000377 if (!(getSTI().getFeatureBits()[Feature])) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000378 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000379 setAvailableFeatures(
380 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000381 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000382 }
383 }
384
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000385 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000386 if (getSTI().getFeatureBits()[Feature]) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000387 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000388 setAvailableFeatures(
389 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000390 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000391 }
392 }
393
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000394 void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
395 setFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000396 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000397 }
398
399 void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
400 clearFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000401 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000402 }
403
Rafael Espindola870c4e92012-01-11 03:56:41 +0000404public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000405 enum MipsMatchResultTy {
Daniel Sanders52da7af2015-11-06 12:11:03 +0000406 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY,
Matheus Almeida595fcab2014-06-11 15:05:56 +0000407#define GET_OPERAND_DIAGNOSTIC_TYPES
408#include "MipsGenAsmMatcher.inc"
409#undef GET_OPERAND_DIAGNOSTIC_TYPES
Matheus Almeida595fcab2014-06-11 15:05:56 +0000410 };
411
Akira Hatanakab11ef082015-11-14 06:35:56 +0000412 MipsAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000413 const MCInstrInfo &MII, const MCTargetOptions &Options)
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000414 : MCTargetAsmParser(Options, sti),
Daniel Sanders50f17232015-09-15 16:17:27 +0000415 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
416 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000417 MCAsmParserExtension::Initialize(parser);
418
Toma Tabacu11e14a92015-04-21 11:50:52 +0000419 parser.addAliasForDirective(".asciiz", ".asciz");
420
Jack Carterb4dbc172012-09-05 23:34:03 +0000421 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000422 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000423
Toma Tabacu9db22db2014-09-09 10:15:38 +0000424 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000425 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000426 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000427
Toma Tabacu9db22db2014-09-09 10:15:38 +0000428 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000429 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000430 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000431
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000432 getTargetStreamer().updateABIInfo(*this);
433
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000434 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000435 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000436
437 CurrentFn = nullptr;
Toma Tabacud88d79c2015-06-23 14:39:42 +0000438
Daniel Sandersa6994442015-08-18 12:33:54 +0000439 IsPicEnabled =
440 (getContext().getObjectFileInfo()->getRelocM() == Reloc::PIC_);
441
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000442 IsCpRestoreSet = false;
443 CpRestoreOffset = -1;
444
Daniel Sanders50f17232015-09-15 16:17:27 +0000445 Triple TheTriple(sti.getTargetTriple());
446 if ((TheTriple.getArch() == Triple::mips) ||
447 (TheTriple.getArch() == Triple::mips64))
Toma Tabacud88d79c2015-06-23 14:39:42 +0000448 IsLittleEndian = false;
449 else
450 IsLittleEndian = true;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000451 }
452
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000453 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
454 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
455
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000456 bool isGP64bit() const {
457 return getSTI().getFeatureBits()[Mips::FeatureGP64Bit];
458 }
459 bool isFP64bit() const {
460 return getSTI().getFeatureBits()[Mips::FeatureFP64Bit];
461 }
Eric Christophera5762812015-01-26 17:33:46 +0000462 const MipsABIInfo &getABI() const { return ABI; }
463 bool isABI_N32() const { return ABI.IsN32(); }
464 bool isABI_N64() const { return ABI.IsN64(); }
465 bool isABI_O32() const { return ABI.IsO32(); }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000466 bool isABI_FPXX() const {
467 return getSTI().getFeatureBits()[Mips::FeatureFPXX];
468 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000469
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000470 bool useOddSPReg() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000471 return !(getSTI().getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000472 }
473
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000474 bool inMicroMipsMode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000475 return getSTI().getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000476 }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000477 bool hasMips1() const {
478 return getSTI().getFeatureBits()[Mips::FeatureMips1];
479 }
480 bool hasMips2() const {
481 return getSTI().getFeatureBits()[Mips::FeatureMips2];
482 }
483 bool hasMips3() const {
484 return getSTI().getFeatureBits()[Mips::FeatureMips3];
485 }
486 bool hasMips4() const {
487 return getSTI().getFeatureBits()[Mips::FeatureMips4];
488 }
489 bool hasMips5() const {
490 return getSTI().getFeatureBits()[Mips::FeatureMips5];
491 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000492 bool hasMips32() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000493 return getSTI().getFeatureBits()[Mips::FeatureMips32];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000494 }
495 bool hasMips64() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000496 return getSTI().getFeatureBits()[Mips::FeatureMips64];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000497 }
498 bool hasMips32r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000499 return getSTI().getFeatureBits()[Mips::FeatureMips32r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000500 }
501 bool hasMips64r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000502 return getSTI().getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000503 }
Daniel Sanders17793142015-02-18 16:24:50 +0000504 bool hasMips32r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000505 return (getSTI().getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000506 }
507 bool hasMips64r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000508 return (getSTI().getFeatureBits()[Mips::FeatureMips64r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000509 }
510 bool hasMips32r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000511 return (getSTI().getFeatureBits()[Mips::FeatureMips32r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000512 }
513 bool hasMips64r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000514 return (getSTI().getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000515 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000516 bool hasMips32r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000517 return getSTI().getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000518 }
519 bool hasMips64r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000520 return getSTI().getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000521 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000522
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000523 bool hasDSP() const {
524 return getSTI().getFeatureBits()[Mips::FeatureDSP];
525 }
526 bool hasDSPR2() const {
527 return getSTI().getFeatureBits()[Mips::FeatureDSPR2];
528 }
529 bool hasDSPR3() const {
530 return getSTI().getFeatureBits()[Mips::FeatureDSPR3];
531 }
532 bool hasMSA() const {
533 return getSTI().getFeatureBits()[Mips::FeatureMSA];
534 }
Kai Nackee0245392015-01-27 19:11:28 +0000535 bool hasCnMips() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000536 return (getSTI().getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000537 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000538
Daniel Sandersa6994442015-08-18 12:33:54 +0000539 bool inPicMode() {
540 return IsPicEnabled;
541 }
542
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000543 bool inMips16Mode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000544 return getSTI().getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000545 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000546
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000547 bool useTraps() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000548 return getSTI().getFeatureBits()[Mips::FeatureUseTCCInDIV];
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000549 }
550
Eric Christophere8ae3e32015-05-07 23:10:21 +0000551 bool useSoftFloat() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000552 return getSTI().getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000553 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000554
Toma Tabacud9d344b2015-04-27 14:05:04 +0000555 /// Warn if RegIndex is the same as the current AT.
556 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000557
558 void warnIfNoMacro(SMLoc Loc);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000559
560 bool isLittle() const { return IsLittleEndian; }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000561};
562}
563
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000564namespace {
565
566/// MipsOperand - Instances of this class represent a parsed Mips machine
567/// instruction.
568class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000569public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000570 /// Broad categories of register classes
571 /// The exact class is finalized by the render method.
572 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000573 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000574 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000575 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000576 RegKind_FCC = 4, /// FCC
577 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
578 RegKind_MSACtrl = 16, /// MSA control registers
579 RegKind_COP2 = 32, /// COP2
580 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
581 /// context).
582 RegKind_CCR = 128, /// CCR
583 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000584 RegKind_COP3 = 512, /// COP3
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000585 RegKind_COP0 = 1024, /// COP0
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000586 /// Potentially any (e.g. $1)
587 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
588 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000589 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
Jack Carter873c7242013-01-12 01:03:14 +0000590 };
591
592private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000593 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000594 k_Immediate, /// An immediate (possibly involving symbol references)
595 k_Memory, /// Base + Offset Memory Address
596 k_PhysRegister, /// A physical register from the Mips namespace
597 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000598 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000599 k_RegList, /// A physical register list
600 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000601 } Kind;
602
David Blaikie960ea3f2014-06-08 16:18:35 +0000603public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000604 MipsOperand(KindTy K, MipsAsmParser &Parser)
605 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
606
David Blaikie960ea3f2014-06-08 16:18:35 +0000607private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000608 /// For diagnostics, and checking the assembler temporary
609 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000610
Eric Christopher8996c5d2013-03-15 00:42:55 +0000611 struct Token {
612 const char *Data;
613 unsigned Length;
614 };
615
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000616 struct PhysRegOp {
617 unsigned Num; /// Register Number
618 };
619
620 struct RegIdxOp {
621 unsigned Index; /// Index into the register class
622 RegKind Kind; /// Bitfield of the kinds it could possibly be
623 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000624 };
625
626 struct ImmOp {
627 const MCExpr *Val;
628 };
629
630 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000631 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000632 const MCExpr *Off;
633 };
634
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000635 struct RegListOp {
636 SmallVector<unsigned, 10> *List;
637 };
638
Jack Carterb4dbc172012-09-05 23:34:03 +0000639 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000640 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000641 struct PhysRegOp PhysReg;
642 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000643 struct ImmOp Imm;
644 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000645 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000646 };
647
648 SMLoc StartLoc, EndLoc;
649
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000650 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000651 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
652 const MCRegisterInfo *RegInfo,
653 SMLoc S, SMLoc E,
654 MipsAsmParser &Parser) {
655 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000656 Op->RegIdx.Index = Index;
657 Op->RegIdx.RegInfo = RegInfo;
658 Op->RegIdx.Kind = RegKind;
659 Op->StartLoc = S;
660 Op->EndLoc = E;
661 return Op;
662 }
663
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000664public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000665 /// Coerce the register to GPR32 and return the real register for the current
666 /// target.
667 unsigned getGPR32Reg() const {
668 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000669 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000670 unsigned ClassID = Mips::GPR32RegClassID;
671 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000672 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000673
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000674 /// Coerce the register to GPR32 and return the real register for the current
675 /// target.
676 unsigned getGPRMM16Reg() const {
677 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
678 unsigned ClassID = Mips::GPR32RegClassID;
679 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
680 }
681
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000682 /// Coerce the register to GPR64 and return the real register for the current
683 /// target.
684 unsigned getGPR64Reg() const {
685 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
686 unsigned ClassID = Mips::GPR64RegClassID;
687 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000688 }
689
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000690private:
691 /// Coerce the register to AFGR64 and return the real register for the current
692 /// target.
693 unsigned getAFGR64Reg() const {
694 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
695 if (RegIdx.Index % 2 != 0)
696 AsmParser.Warning(StartLoc, "Float register should be even.");
697 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
698 .getRegister(RegIdx.Index / 2);
699 }
700
701 /// Coerce the register to FGR64 and return the real register for the current
702 /// target.
703 unsigned getFGR64Reg() const {
704 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
705 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
706 .getRegister(RegIdx.Index);
707 }
708
709 /// Coerce the register to FGR32 and return the real register for the current
710 /// target.
711 unsigned getFGR32Reg() const {
712 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
713 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
714 .getRegister(RegIdx.Index);
715 }
716
717 /// Coerce the register to FGRH32 and return the real register for the current
718 /// target.
719 unsigned getFGRH32Reg() const {
720 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
721 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
722 .getRegister(RegIdx.Index);
723 }
724
725 /// Coerce the register to FCC and return the real register for the current
726 /// target.
727 unsigned getFCCReg() const {
728 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
729 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
730 .getRegister(RegIdx.Index);
731 }
732
733 /// Coerce the register to MSA128 and return the real register for the current
734 /// target.
735 unsigned getMSA128Reg() const {
736 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
737 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
738 // identical
739 unsigned ClassID = Mips::MSA128BRegClassID;
740 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
741 }
742
743 /// Coerce the register to MSACtrl and return the real register for the
744 /// current target.
745 unsigned getMSACtrlReg() const {
746 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
747 unsigned ClassID = Mips::MSACtrlRegClassID;
748 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
749 }
750
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000751 /// Coerce the register to COP0 and return the real register for the
752 /// current target.
753 unsigned getCOP0Reg() const {
754 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");
755 unsigned ClassID = Mips::COP0RegClassID;
756 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
757 }
758
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000759 /// Coerce the register to COP2 and return the real register for the
760 /// current target.
761 unsigned getCOP2Reg() const {
762 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
763 unsigned ClassID = Mips::COP2RegClassID;
764 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
765 }
766
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000767 /// Coerce the register to COP3 and return the real register for the
768 /// current target.
769 unsigned getCOP3Reg() const {
770 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
771 unsigned ClassID = Mips::COP3RegClassID;
772 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
773 }
774
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000775 /// Coerce the register to ACC64DSP and return the real register for the
776 /// current target.
777 unsigned getACC64DSPReg() const {
778 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
779 unsigned ClassID = Mips::ACC64DSPRegClassID;
780 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
781 }
782
783 /// Coerce the register to HI32DSP and return the real register for the
784 /// current target.
785 unsigned getHI32DSPReg() const {
786 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
787 unsigned ClassID = Mips::HI32DSPRegClassID;
788 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
789 }
790
791 /// Coerce the register to LO32DSP and return the real register for the
792 /// current target.
793 unsigned getLO32DSPReg() const {
794 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
795 unsigned ClassID = Mips::LO32DSPRegClassID;
796 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
797 }
798
799 /// Coerce the register to CCR and return the real register for the
800 /// current target.
801 unsigned getCCRReg() const {
802 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
803 unsigned ClassID = Mips::CCRRegClassID;
804 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
805 }
806
807 /// Coerce the register to HWRegs and return the real register for the
808 /// current target.
809 unsigned getHWRegsReg() const {
810 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
811 unsigned ClassID = Mips::HWRegsRegClassID;
812 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
813 }
814
815public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000816 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000817 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000818 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000819 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000820 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000821 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000822 else
Jim Grosbache9119e42015-05-13 18:37:00 +0000823 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000824 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000825
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000826 void addRegOperands(MCInst &Inst, unsigned N) const {
827 llvm_unreachable("Use a custom parser instead");
828 }
829
Daniel Sanders21bce302014-04-01 12:35:23 +0000830 /// Render the operand to an MCInst as a GPR32
831 /// Asserts if the wrong number of operands are requested, or the operand
832 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000833 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
834 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000835 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000836 }
837
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000838 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
839 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000840 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000841 }
842
Jozef Kolek1904fa22014-11-24 14:25:53 +0000843 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
844 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000845 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +0000846 }
847
Zoran Jovanovic41688672015-02-10 16:36:20 +0000848 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
849 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000850 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000851 }
852
Daniel Sanders21bce302014-04-01 12:35:23 +0000853 /// Render the operand to an MCInst as a GPR64
854 /// Asserts if the wrong number of operands are requested, or the operand
855 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000856 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
857 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000858 Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000859 }
860
861 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
862 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000863 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000864 }
865
866 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
867 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000868 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000869 }
870
871 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
872 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000873 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000874 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000875 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000876 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
877 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000878 }
879
880 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
881 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000882 Inst.addOperand(MCOperand::createReg(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000883 }
884
885 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
886 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000887 Inst.addOperand(MCOperand::createReg(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000888 }
889
890 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
891 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000892 Inst.addOperand(MCOperand::createReg(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000893 }
894
895 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
896 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000897 Inst.addOperand(MCOperand::createReg(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000898 }
899
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000900 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
901 assert(N == 1 && "Invalid number of operands!");
902 Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
903 }
904
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000905 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
906 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000907 Inst.addOperand(MCOperand::createReg(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000908 }
909
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000910 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
911 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000912 Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000913 }
914
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000915 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
916 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000917 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000918 }
919
920 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
921 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000922 Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000923 }
924
925 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
926 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000927 Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000928 }
929
930 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
931 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000932 Inst.addOperand(MCOperand::createReg(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000933 }
934
935 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
936 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000937 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000938 }
939
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +0000940 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
Daniel Sanders52da7af2015-11-06 12:11:03 +0000941 void addConstantUImmOperands(MCInst &Inst, unsigned N) const {
942 assert(N == 1 && "Invalid number of operands!");
Daniel Sandersea4f6532015-11-06 12:22:31 +0000943 uint64_t Imm = getConstantImm() - Offset;
944 Imm &= (1 << Bits) - 1;
945 Imm += Offset;
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +0000946 Imm += AdjustOffset;
Daniel Sanders52da7af2015-11-06 12:11:03 +0000947 Inst.addOperand(MCOperand::createImm(Imm));
948 }
949
Daniel Sandersf8bb23e2016-02-01 15:13:31 +0000950 template <unsigned Bits>
951 void addUImmOperands(MCInst &Inst, unsigned N) const {
952 if (isImm() && !isConstantImm()) {
953 addExpr(Inst, getImm());
954 return;
955 }
956 addConstantUImmOperands<Bits, 0, 0>(Inst, N);
957 }
958
Daniel Sanders78e89022016-03-11 11:37:50 +0000959 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
960 void addConstantSImmOperands(MCInst &Inst, unsigned N) const {
961 assert(N == 1 && "Invalid number of operands!");
962 int64_t Imm = getConstantImm() - Offset;
963 Imm = SignExtend64<Bits>(Imm);
964 Imm += Offset;
965 Imm += AdjustOffset;
966 Inst.addOperand(MCOperand::createImm(Imm));
967 }
968
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000969 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000970 assert(N == 1 && "Invalid number of operands!");
971 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000972 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000973 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000974
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000975 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000976 assert(N == 2 && "Invalid number of operands!");
977
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000978 Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
979 ? getMemBase()->getGPR64Reg()
980 : getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000981
982 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000983 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000984 }
985
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000986 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
987 assert(N == 2 && "Invalid number of operands!");
988
Jim Grosbache9119e42015-05-13 18:37:00 +0000989 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000990
991 const MCExpr *Expr = getMemOff();
992 addExpr(Inst, Expr);
993 }
994
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000995 void addRegListOperands(MCInst &Inst, unsigned N) const {
996 assert(N == 1 && "Invalid number of operands!");
997
998 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000999 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001000 }
1001
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001002 void addRegPairOperands(MCInst &Inst, unsigned N) const {
1003 assert(N == 2 && "Invalid number of operands!");
1004 unsigned RegNo = getRegPair();
Jim Grosbache9119e42015-05-13 18:37:00 +00001005 Inst.addOperand(MCOperand::createReg(RegNo++));
1006 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001007 }
1008
Zoran Jovanovic41688672015-02-10 16:36:20 +00001009 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
1010 assert(N == 2 && "Invalid number of operands!");
1011 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001012 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +00001013 }
1014
Craig Topper56c590a2014-04-29 07:58:02 +00001015 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001016 // As a special case until we sort out the definition of div/divu, pretend
1017 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
1018 if (isGPRAsmReg() && RegIdx.Index == 0)
1019 return true;
1020
1021 return Kind == k_PhysRegister;
1022 }
1023 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +00001024 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001025 bool isConstantImm() const {
Craig Topper66059c92015-11-18 07:07:59 +00001026 return isImm() && isa<MCConstantExpr>(getImm());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001027 }
Daniel Sanders52da7af2015-11-06 12:11:03 +00001028 bool isConstantImmz() const {
1029 return isConstantImm() && getConstantImm() == 0;
1030 }
Daniel Sandersea4f6532015-11-06 12:22:31 +00001031 template <unsigned Bits, int Offset = 0> bool isConstantUImm() const {
1032 return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset);
1033 }
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001034 template <unsigned Bits> bool isUImm() const {
1035 return isConstantImm() ? isUInt<Bits>(getConstantImm()) : isImm();
1036 }
1037 template <unsigned Bits> bool isAnyImm() const {
1038 return isConstantImm() ? (isInt<Bits>(getConstantImm()) ||
1039 isUInt<Bits>(getConstantImm()))
1040 : isImm();
1041 }
Daniel Sanders78e89022016-03-11 11:37:50 +00001042 template <unsigned Bits, int Offset = 0> bool isConstantSImm() const {
1043 return isConstantImm() && isInt<Bits>(getConstantImm() - Offset);
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +00001044 }
Hrvoje Varga46458d02016-02-25 12:53:29 +00001045 template <unsigned Bottom, unsigned Top> bool isConstantUImmRange() const {
1046 return isConstantImm() && getConstantImm() >= Bottom &&
1047 getConstantImm() <= Top;
1048 }
Craig Topper56c590a2014-04-29 07:58:02 +00001049 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001050 // Note: It's not possible to pretend that other operand kinds are tokens.
1051 // The matcher emitter checks tokens first.
1052 return Kind == k_Token;
1053 }
Craig Topper56c590a2014-04-29 07:58:02 +00001054 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001055 bool isConstantMemOff() const {
Craig Topper66059c92015-11-18 07:07:59 +00001056 return isMem() && isa<MCConstantExpr>(getMemOff());
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001057 }
1058 template <unsigned Bits> bool isMemWithSimmOffset() const {
Zoran Jovanovica6593ff2015-08-18 12:53:08 +00001059 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
1060 && getMemBase()->isGPRAsmReg();
1061 }
Zoran Jovanovic6e6a2c92015-09-16 09:14:35 +00001062 template <unsigned Bits> bool isMemWithSimmOffsetGPR() const {
1063 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff()) &&
1064 getMemBase()->isGPRAsmReg();
1065 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001066 bool isMemWithGRPMM16Base() const {
1067 return isMem() && getMemBase()->isMM16AsmReg();
1068 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001069 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
1070 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1071 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
1072 }
Jozef Kolek12c69822014-12-23 16:16:33 +00001073 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
1074 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1075 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1076 && (getMemBase()->getGPR32Reg() == Mips::SP);
1077 }
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001078 template <unsigned Bits, unsigned ShiftLeftAmount>
1079 bool isScaledUImm() const {
1080 return isConstantImm() &&
1081 isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm());
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00001082 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001083 bool isRegList16() const {
1084 if (!isRegList())
1085 return false;
1086
1087 int Size = RegList.List->size();
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001088 if (Size < 2 || Size > 5)
1089 return false;
1090
1091 unsigned R0 = RegList.List->front();
1092 unsigned R1 = RegList.List->back();
1093 if (!((R0 == Mips::S0 && R1 == Mips::RA) ||
1094 (R0 == Mips::S0_64 && R1 == Mips::RA_64)))
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001095 return false;
1096
1097 int PrevReg = *RegList.List->begin();
1098 for (int i = 1; i < Size - 1; i++) {
1099 int Reg = (*(RegList.List))[i];
1100 if ( Reg != PrevReg + 1)
1101 return false;
1102 PrevReg = Reg;
1103 }
1104
1105 return true;
1106 }
Vladimir Medic2b953d02013-10-01 09:48:56 +00001107 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001108 bool isLSAImm() const {
1109 if (!isConstantImm())
1110 return false;
1111 int64_t Val = getConstantImm();
1112 return 1 <= Val && Val <= 4;
1113 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001114 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001115 bool isMovePRegPair() const {
1116 if (Kind != k_RegList || RegList.List->size() != 2)
1117 return false;
1118
1119 unsigned R0 = RegList.List->front();
1120 unsigned R1 = RegList.List->back();
1121
1122 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
1123 (R0 == Mips::A1 && R1 == Mips::A3) ||
1124 (R0 == Mips::A2 && R1 == Mips::A3) ||
1125 (R0 == Mips::A0 && R1 == Mips::S5) ||
1126 (R0 == Mips::A0 && R1 == Mips::S6) ||
1127 (R0 == Mips::A0 && R1 == Mips::A1) ||
1128 (R0 == Mips::A0 && R1 == Mips::A2) ||
1129 (R0 == Mips::A0 && R1 == Mips::A3))
1130 return true;
1131
1132 return false;
1133 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001134
1135 StringRef getToken() const {
1136 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001137 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001138 }
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001139 bool isRegPair() const { return Kind == k_RegPair; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001140
Craig Topper56c590a2014-04-29 07:58:02 +00001141 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001142 // As a special case until we sort out the definition of div/divu, pretend
1143 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
1144 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1145 RegIdx.Kind & RegKind_GPR)
1146 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001147
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001148 assert(Kind == k_PhysRegister && "Invalid access!");
1149 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +00001150 }
1151
Jack Carterb4dbc172012-09-05 23:34:03 +00001152 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001153 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001154 return Imm.Val;
1155 }
1156
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001157 int64_t getConstantImm() const {
1158 const MCExpr *Val = getImm();
1159 return static_cast<const MCConstantExpr *>(Val)->getValue();
1160 }
1161
1162 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001163 assert((Kind == k_Memory) && "Invalid access!");
1164 return Mem.Base;
1165 }
1166
1167 const MCExpr *getMemOff() const {
1168 assert((Kind == k_Memory) && "Invalid access!");
1169 return Mem.Off;
1170 }
1171
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001172 int64_t getConstantMemOff() const {
1173 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1174 }
1175
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001176 const SmallVectorImpl<unsigned> &getRegList() const {
1177 assert((Kind == k_RegList) && "Invalid access!");
1178 return *(RegList.List);
1179 }
1180
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001181 unsigned getRegPair() const {
1182 assert((Kind == k_RegPair) && "Invalid access!");
1183 return RegIdx.Index;
1184 }
1185
David Blaikie960ea3f2014-06-08 16:18:35 +00001186 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1187 MipsAsmParser &Parser) {
1188 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001189 Op->Tok.Data = Str.data();
1190 Op->Tok.Length = Str.size();
1191 Op->StartLoc = S;
1192 Op->EndLoc = S;
1193 return Op;
1194 }
1195
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001196 /// Create a numeric register (e.g. $1). The exact register remains
1197 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001198 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001199 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001200 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001201 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001202 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001203 }
1204
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001205 /// Create a register that is definitely a GPR.
1206 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001207 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001208 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001209 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001210 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001211 }
1212
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001213 /// Create a register that is definitely a FGR.
1214 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001215 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001216 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001217 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001218 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
1219 }
1220
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001221 /// Create a register that is definitely a HWReg.
1222 /// This is typically only used for named registers such as $hwr_cpunum.
1223 static std::unique_ptr<MipsOperand>
1224 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
1225 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1226 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
1227 }
1228
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001229 /// Create a register that is definitely an FCC.
1230 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001231 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001232 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001233 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001234 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
1235 }
1236
1237 /// Create a register that is definitely an ACC.
1238 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001239 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001240 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001241 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001242 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
1243 }
1244
1245 /// Create a register that is definitely an MSA128.
1246 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001247 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001248 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001249 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001250 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
1251 }
1252
1253 /// Create a register that is definitely an MSACtrl.
1254 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001255 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001256 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001257 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001258 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
1259 }
1260
David Blaikie960ea3f2014-06-08 16:18:35 +00001261 static std::unique_ptr<MipsOperand>
1262 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1263 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001264 Op->Imm.Val = Val;
1265 Op->StartLoc = S;
1266 Op->EndLoc = E;
1267 return Op;
1268 }
1269
David Blaikie960ea3f2014-06-08 16:18:35 +00001270 static std::unique_ptr<MipsOperand>
1271 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1272 SMLoc E, MipsAsmParser &Parser) {
1273 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1274 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001275 Op->Mem.Off = Off;
1276 Op->StartLoc = S;
1277 Op->EndLoc = E;
1278 return Op;
1279 }
1280
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001281 static std::unique_ptr<MipsOperand>
1282 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1283 MipsAsmParser &Parser) {
1284 assert (Regs.size() > 0 && "Empty list not allowed");
1285
1286 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001287 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001288 Op->StartLoc = StartLoc;
1289 Op->EndLoc = EndLoc;
1290 return Op;
1291 }
1292
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001293 static std::unique_ptr<MipsOperand>
1294 CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1295 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
1296 Op->RegIdx.Index = RegNo;
1297 Op->StartLoc = S;
1298 Op->EndLoc = E;
1299 return Op;
1300 }
1301
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001302 bool isGPRAsmReg() const {
1303 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001304 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001305 bool isMM16AsmReg() const {
1306 if (!(isRegIdx() && RegIdx.Kind))
1307 return false;
1308 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1309 || RegIdx.Index == 16 || RegIdx.Index == 17);
1310 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001311 bool isMM16AsmRegZero() const {
1312 if (!(isRegIdx() && RegIdx.Kind))
1313 return false;
1314 return (RegIdx.Index == 0 ||
1315 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1316 RegIdx.Index == 17);
1317 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001318 bool isMM16AsmRegMoveP() const {
1319 if (!(isRegIdx() && RegIdx.Kind))
1320 return false;
1321 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1322 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1323 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001324 bool isFGRAsmReg() const {
1325 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1326 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001327 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001328 bool isHWRegsAsmReg() const {
1329 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001330 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001331 bool isCCRAsmReg() const {
1332 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001333 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001334 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001335 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1336 return false;
1337 if (!AsmParser.hasEightFccRegisters())
1338 return RegIdx.Index == 0;
1339 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001340 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001341 bool isACCAsmReg() const {
1342 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001343 }
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001344 bool isCOP0AsmReg() const {
1345 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1346 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001347 bool isCOP2AsmReg() const {
1348 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001349 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001350 bool isCOP3AsmReg() const {
1351 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1352 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001353 bool isMSA128AsmReg() const {
1354 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001355 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001356 bool isMSACtrlAsmReg() const {
1357 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001358 }
1359
Jack Carterb4dbc172012-09-05 23:34:03 +00001360 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001361 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001362 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001363 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001364
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001365 virtual ~MipsOperand() {
1366 switch (Kind) {
1367 case k_Immediate:
1368 break;
1369 case k_Memory:
1370 delete Mem.Base;
1371 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001372 case k_RegList:
1373 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001374 case k_PhysRegister:
1375 case k_RegisterIndex:
1376 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001377 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001378 break;
1379 }
1380 }
1381
Craig Topper56c590a2014-04-29 07:58:02 +00001382 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001383 switch (Kind) {
1384 case k_Immediate:
1385 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001386 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001387 OS << ">";
1388 break;
1389 case k_Memory:
1390 OS << "Mem<";
1391 Mem.Base->print(OS);
1392 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001393 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001394 OS << ">";
1395 break;
1396 case k_PhysRegister:
1397 OS << "PhysReg<" << PhysReg.Num << ">";
1398 break;
1399 case k_RegisterIndex:
1400 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1401 break;
1402 case k_Token:
1403 OS << Tok.Data;
1404 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001405 case k_RegList:
1406 OS << "RegList< ";
1407 for (auto Reg : (*RegList.List))
1408 OS << Reg << " ";
1409 OS << ">";
1410 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001411 case k_RegPair:
1412 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1413 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001414 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001415 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001416}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001417} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001418
Jack Carter9e65aa32013-03-22 00:05:30 +00001419namespace llvm {
1420extern const MCInstrDesc MipsInsts[];
1421}
1422static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1423 return MipsInsts[Opcode];
1424}
1425
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001426static bool hasShortDelaySlot(unsigned Opcode) {
1427 switch (Opcode) {
1428 case Mips::JALS_MM:
1429 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001430 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001431 case Mips::BGEZALS_MM:
1432 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001433 return true;
1434 default:
1435 return false;
1436 }
1437}
1438
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001439static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1440 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1441 return &SRExpr->getSymbol();
1442 }
1443
1444 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1445 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1446 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1447
1448 if (LHSSym)
1449 return LHSSym;
1450
1451 if (RHSSym)
1452 return RHSSym;
1453
1454 return nullptr;
1455 }
1456
1457 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1458 return getSingleMCSymbol(UExpr->getSubExpr());
1459
1460 return nullptr;
1461}
1462
1463static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1464 if (isa<MCSymbolRefExpr>(Expr))
1465 return 1;
1466
1467 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1468 return countMCSymbolRefExpr(BExpr->getLHS()) +
1469 countMCSymbolRefExpr(BExpr->getRHS());
1470
1471 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1472 return countMCSymbolRefExpr(UExpr->getSubExpr());
1473
1474 return 0;
1475}
1476
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001477namespace {
1478void emitRX(unsigned Opcode, unsigned Reg0, MCOperand Op1, SMLoc IDLoc,
1479 SmallVectorImpl<MCInst> &Instructions) {
1480 MCInst tmpInst;
1481 tmpInst.setOpcode(Opcode);
1482 tmpInst.addOperand(MCOperand::createReg(Reg0));
1483 tmpInst.addOperand(Op1);
1484 tmpInst.setLoc(IDLoc);
1485 Instructions.push_back(tmpInst);
1486}
1487
1488void emitRI(unsigned Opcode, unsigned Reg0, int32_t Imm, SMLoc IDLoc,
1489 SmallVectorImpl<MCInst> &Instructions) {
1490 emitRX(Opcode, Reg0, MCOperand::createImm(Imm), IDLoc, Instructions);
1491}
1492
1493void emitRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, SMLoc IDLoc,
1494 SmallVectorImpl<MCInst> &Instructions) {
1495 emitRX(Opcode, Reg0, MCOperand::createReg(Reg1), IDLoc, Instructions);
1496}
1497
1498void emitII(unsigned Opcode, int16_t Imm1, int16_t Imm2, SMLoc IDLoc,
1499 SmallVectorImpl<MCInst> &Instructions) {
1500 MCInst tmpInst;
1501 tmpInst.setOpcode(Opcode);
1502 tmpInst.addOperand(MCOperand::createImm(Imm1));
1503 tmpInst.addOperand(MCOperand::createImm(Imm2));
1504 tmpInst.setLoc(IDLoc);
1505 Instructions.push_back(tmpInst);
1506}
1507
1508void emitR(unsigned Opcode, unsigned Reg0, SMLoc IDLoc,
1509 SmallVectorImpl<MCInst> &Instructions) {
1510 MCInst tmpInst;
1511 tmpInst.setOpcode(Opcode);
1512 tmpInst.addOperand(MCOperand::createReg(Reg0));
1513 tmpInst.setLoc(IDLoc);
1514 Instructions.push_back(tmpInst);
1515}
1516
1517void emitRRX(unsigned Opcode, unsigned Reg0, unsigned Reg1, MCOperand Op2,
1518 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1519 MCInst tmpInst;
1520 tmpInst.setOpcode(Opcode);
1521 tmpInst.addOperand(MCOperand::createReg(Reg0));
1522 tmpInst.addOperand(MCOperand::createReg(Reg1));
1523 tmpInst.addOperand(Op2);
1524 tmpInst.setLoc(IDLoc);
1525 Instructions.push_back(tmpInst);
1526}
1527
1528void emitRRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, unsigned Reg2,
1529 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1530 emitRRX(Opcode, Reg0, Reg1, MCOperand::createReg(Reg2), IDLoc,
1531 Instructions);
1532}
1533
1534void emitRRI(unsigned Opcode, unsigned Reg0, unsigned Reg1, int16_t Imm,
1535 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1536 emitRRX(Opcode, Reg0, Reg1, MCOperand::createImm(Imm), IDLoc,
1537 Instructions);
1538}
1539
1540void emitAppropriateDSLL(unsigned DstReg, unsigned SrcReg, int16_t ShiftAmount,
1541 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1542 if (ShiftAmount >= 32) {
1543 emitRRI(Mips::DSLL32, DstReg, SrcReg, ShiftAmount - 32, IDLoc,
1544 Instructions);
1545 return;
1546 }
1547
1548 emitRRI(Mips::DSLL, DstReg, SrcReg, ShiftAmount, IDLoc, Instructions);
1549}
1550} // end anonymous namespace.
1551
Jack Carter9e65aa32013-03-22 00:05:30 +00001552bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001553 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001554 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001555 bool ExpandedJalSym = false;
Daniel Sandersa771fef2014-03-24 14:05:39 +00001556
Jack Carter9e65aa32013-03-22 00:05:30 +00001557 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001558
1559 if (MCID.isBranch() || MCID.isCall()) {
1560 const unsigned Opcode = Inst.getOpcode();
1561 MCOperand Offset;
1562
1563 switch (Opcode) {
1564 default:
1565 break;
Kai Nackee0245392015-01-27 19:11:28 +00001566 case Mips::BBIT0:
1567 case Mips::BBIT032:
1568 case Mips::BBIT1:
1569 case Mips::BBIT132:
1570 assert(hasCnMips() && "instruction only valid for octeon cpus");
1571 // Fall through
1572
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001573 case Mips::BEQ:
1574 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001575 case Mips::BEQ_MM:
1576 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001577 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001578 Offset = Inst.getOperand(2);
1579 if (!Offset.isImm())
1580 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001581 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001582 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001583 if (OffsetToAlignment(Offset.getImm(),
1584 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001585 return Error(IDLoc, "branch to misaligned address");
1586 break;
1587 case Mips::BGEZ:
1588 case Mips::BGTZ:
1589 case Mips::BLEZ:
1590 case Mips::BLTZ:
1591 case Mips::BGEZAL:
1592 case Mips::BLTZAL:
1593 case Mips::BC1F:
1594 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001595 case Mips::BGEZ_MM:
1596 case Mips::BGTZ_MM:
1597 case Mips::BLEZ_MM:
1598 case Mips::BLTZ_MM:
1599 case Mips::BGEZAL_MM:
1600 case Mips::BLTZAL_MM:
1601 case Mips::BC1F_MM:
1602 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001603 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001604 Offset = Inst.getOperand(1);
1605 if (!Offset.isImm())
1606 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001607 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001608 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001609 if (OffsetToAlignment(Offset.getImm(),
1610 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001611 return Error(IDLoc, "branch to misaligned address");
1612 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001613 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001614 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001615 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001616 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001617 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1618 Offset = Inst.getOperand(1);
1619 if (!Offset.isImm())
1620 break; // We'll deal with this situation later on when applying fixups.
Craig Topper55b1f292015-10-10 20:17:07 +00001621 if (!isInt<8>(Offset.getImm()))
Jozef Kolek9761e962015-01-12 12:03:34 +00001622 return Error(IDLoc, "branch target out of range");
1623 if (OffsetToAlignment(Offset.getImm(), 2LL))
1624 return Error(IDLoc, "branch to misaligned address");
1625 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001626 }
1627 }
1628
Daniel Sandersa84989a2014-06-16 13:25:35 +00001629 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1630 // We still accept it but it is a normal nop.
1631 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1632 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1633 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1634 "nop instruction");
1635 }
1636
Kai Nackee0245392015-01-27 19:11:28 +00001637 if (hasCnMips()) {
1638 const unsigned Opcode = Inst.getOpcode();
1639 MCOperand Opnd;
1640 int Imm;
1641
1642 switch (Opcode) {
1643 default:
1644 break;
1645
1646 case Mips::BBIT0:
1647 case Mips::BBIT032:
1648 case Mips::BBIT1:
1649 case Mips::BBIT132:
1650 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1651 // The offset is handled above
1652 Opnd = Inst.getOperand(1);
1653 if (!Opnd.isImm())
1654 return Error(IDLoc, "expected immediate operand kind");
1655 Imm = Opnd.getImm();
1656 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1657 Opcode == Mips::BBIT1 ? 63 : 31))
1658 return Error(IDLoc, "immediate operand value out of range");
1659 if (Imm > 31) {
1660 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1661 : Mips::BBIT132);
1662 Inst.getOperand(1).setImm(Imm - 32);
1663 }
1664 break;
1665
Kai Nackee0245392015-01-27 19:11:28 +00001666 case Mips::SEQi:
1667 case Mips::SNEi:
1668 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1669 Opnd = Inst.getOperand(2);
1670 if (!Opnd.isImm())
1671 return Error(IDLoc, "expected immediate operand kind");
1672 Imm = Opnd.getImm();
1673 if (!isInt<10>(Imm))
1674 return Error(IDLoc, "immediate operand value out of range");
1675 break;
1676 }
1677 }
1678
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001679 // This expansion is not in a function called by tryExpandInstruction()
1680 // because the pseudo-instruction doesn't have a distinct opcode.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001681 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
1682 inPicMode()) {
1683 warnIfNoMacro(IDLoc);
1684
1685 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
1686
1687 // We can do this expansion if there's only 1 symbol in the argument
1688 // expression.
1689 if (countMCSymbolRefExpr(JalExpr) > 1)
1690 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
1691
1692 // FIXME: This is checking the expression can be handled by the later stages
1693 // of the assembler. We ought to leave it to those later stages but
1694 // we can't do that until we stop evaluateRelocExpr() rewriting the
1695 // expressions into non-equivalent forms.
1696 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
1697
1698 // FIXME: Add support for label+offset operands (currently causes an error).
1699 // FIXME: Add support for forward-declared local symbols.
1700 // FIXME: Add expansion for when the LargeGOT option is enabled.
1701 if (JalSym->isInSection() || JalSym->isTemporary()) {
1702 if (isABI_O32()) {
1703 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001704 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001705 // R_(MICRO)MIPS_GOT16 label
1706 // addiu $25, $25, 0
1707 // R_(MICRO)MIPS_LO16 label
1708 // jalr $25
1709 const MCExpr *Got16RelocExpr = evaluateRelocExpr(JalExpr, "got");
1710 const MCExpr *Lo16RelocExpr = evaluateRelocExpr(JalExpr, "lo");
1711
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001712 emitRRX(Mips::LW, Mips::T9, Mips::GP,
1713 MCOperand::createExpr(Got16RelocExpr), IDLoc, Instructions);
1714 emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
1715 MCOperand::createExpr(Lo16RelocExpr), IDLoc, Instructions);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001716 } else if (isABI_N32() || isABI_N64()) {
1717 // If it's a local symbol and the N32/N64 ABIs are being used,
1718 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001719 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001720 // R_(MICRO)MIPS_GOT_DISP label
1721 // jalr $25
1722 const MCExpr *GotDispRelocExpr = evaluateRelocExpr(JalExpr, "got_disp");
1723
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001724 emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
1725 MCOperand::createExpr(GotDispRelocExpr), IDLoc, Instructions);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001726 }
1727 } else {
Daniel Sandersb7002032015-11-20 13:16:35 +00001728 // If it's an external/weak symbol, we expand to:
1729 // lw/ld $25, 0($gp)
1730 // R_(MICRO)MIPS_CALL16 label
1731 // jalr $25
1732 const MCExpr *Call16RelocExpr = evaluateRelocExpr(JalExpr, "call16");
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001733
Daniel Sandersb7002032015-11-20 13:16:35 +00001734 emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
1735 MCOperand::createExpr(Call16RelocExpr), IDLoc, Instructions);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001736 }
1737
1738 MCInst JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001739 if (IsCpRestoreSet && inMicroMipsMode())
1740 JalrInst.setOpcode(Mips::JALRS_MM);
1741 else
1742 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001743 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
1744 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
1745
1746 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
1747 // This relocation is supposed to be an optimization hint for the linker
1748 // and is not necessary for correctness.
1749
1750 Inst = JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001751 ExpandedJalSym = true;
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001752 }
1753
Jack Carter9e65aa32013-03-22 00:05:30 +00001754 if (MCID.mayLoad() || MCID.mayStore()) {
1755 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001756 // reference or immediate we may have to expand instructions.
1757 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001758 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001759 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1760 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001761 MCOperand &Op = Inst.getOperand(i);
1762 if (Op.isImm()) {
1763 int MemOffset = Op.getImm();
1764 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001765 // Offset can't exceed 16bit value.
1766 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001767 return false;
1768 }
1769 } else if (Op.isExpr()) {
1770 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001771 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001772 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001773 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001774 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001775 // Expand symbol.
1776 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001777 return false;
1778 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001779 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001780 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001781 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001782 }
1783 }
1784 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001785 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001786 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001787
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001788 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001789 if (MCID.mayLoad()) {
1790 // Try to create 16-bit GP relative load instruction.
1791 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1792 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1793 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1794 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1795 MCOperand &Op = Inst.getOperand(i);
1796 if (Op.isImm()) {
1797 int MemOffset = Op.getImm();
1798 MCOperand &DstReg = Inst.getOperand(0);
1799 MCOperand &BaseReg = Inst.getOperand(1);
Craig Topper55b1f292015-10-10 20:17:07 +00001800 if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&
Jozef Koleke10a02e2015-01-28 17:27:26 +00001801 getContext().getRegisterInfo()->getRegClass(
1802 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00001803 (BaseReg.getReg() == Mips::GP ||
1804 BaseReg.getReg() == Mips::GP_64)) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001805
1806 emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
1807 IDLoc, Instructions);
Jozef Koleke10a02e2015-01-28 17:27:26 +00001808 return false;
1809 }
1810 }
1811 }
1812 } // for
1813 } // if load
1814
1815 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1816
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001817 MCOperand Opnd;
1818 int Imm;
1819
1820 switch (Inst.getOpcode()) {
1821 default:
1822 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001823 case Mips::ADDIUSP_MM:
1824 Opnd = Inst.getOperand(0);
1825 if (!Opnd.isImm())
1826 return Error(IDLoc, "expected immediate operand kind");
1827 Imm = Opnd.getImm();
1828 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1829 Imm % 4 != 0)
1830 return Error(IDLoc, "immediate operand value out of range");
1831 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001832 case Mips::SLL16_MM:
1833 case Mips::SRL16_MM:
1834 Opnd = Inst.getOperand(2);
1835 if (!Opnd.isImm())
1836 return Error(IDLoc, "expected immediate operand kind");
1837 Imm = Opnd.getImm();
1838 if (Imm < 1 || Imm > 8)
1839 return Error(IDLoc, "immediate operand value out of range");
1840 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001841 case Mips::LI16_MM:
1842 Opnd = Inst.getOperand(1);
1843 if (!Opnd.isImm())
1844 return Error(IDLoc, "expected immediate operand kind");
1845 Imm = Opnd.getImm();
1846 if (Imm < -1 || Imm > 126)
1847 return Error(IDLoc, "immediate operand value out of range");
1848 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001849 case Mips::ADDIUR2_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 == -1 ||
1855 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1856 return Error(IDLoc, "immediate operand value out of range");
1857 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001858 case Mips::ANDI16_MM:
1859 Opnd = Inst.getOperand(2);
1860 if (!Opnd.isImm())
1861 return Error(IDLoc, "expected immediate operand kind");
1862 Imm = Opnd.getImm();
1863 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1864 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1865 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1866 return Error(IDLoc, "immediate operand value out of range");
1867 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001868 case Mips::LBU16_MM:
1869 Opnd = Inst.getOperand(2);
1870 if (!Opnd.isImm())
1871 return Error(IDLoc, "expected immediate operand kind");
1872 Imm = Opnd.getImm();
1873 if (Imm < -1 || Imm > 14)
1874 return Error(IDLoc, "immediate operand value out of range");
1875 break;
1876 case Mips::SB16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001877 case Mips::SB16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001878 Opnd = Inst.getOperand(2);
1879 if (!Opnd.isImm())
1880 return Error(IDLoc, "expected immediate operand kind");
1881 Imm = Opnd.getImm();
1882 if (Imm < 0 || Imm > 15)
1883 return Error(IDLoc, "immediate operand value out of range");
1884 break;
1885 case Mips::LHU16_MM:
1886 case Mips::SH16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001887 case Mips::SH16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001888 Opnd = Inst.getOperand(2);
1889 if (!Opnd.isImm())
1890 return Error(IDLoc, "expected immediate operand kind");
1891 Imm = Opnd.getImm();
1892 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1893 return Error(IDLoc, "immediate operand value out of range");
1894 break;
1895 case Mips::LW16_MM:
1896 case Mips::SW16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001897 case Mips::SW16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001898 Opnd = Inst.getOperand(2);
1899 if (!Opnd.isImm())
1900 return Error(IDLoc, "expected immediate operand kind");
1901 Imm = Opnd.getImm();
1902 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1903 return Error(IDLoc, "immediate operand value out of range");
1904 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001905 case Mips::ADDIUPC_MM:
1906 MCOperand Opnd = Inst.getOperand(1);
1907 if (!Opnd.isImm())
1908 return Error(IDLoc, "expected immediate operand kind");
1909 int Imm = Opnd.getImm();
Craig Topper55b1f292015-10-10 20:17:07 +00001910 if ((Imm % 4 != 0) || !isInt<25>(Imm))
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001911 return Error(IDLoc, "immediate operand value out of range");
1912 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001913 }
1914 }
1915
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001916 MacroExpanderResultTy ExpandResult =
1917 tryExpandInstruction(Inst, IDLoc, Instructions);
1918 switch (ExpandResult) {
1919 case MER_NotAMacro:
Jack Carter9e65aa32013-03-22 00:05:30 +00001920 Instructions.push_back(Inst);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001921 break;
1922 case MER_Success:
1923 break;
1924 case MER_Fail:
1925 return true;
1926 }
Jack Carter9e65aa32013-03-22 00:05:30 +00001927
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001928 // If this instruction has a delay slot and .set reorder is active,
1929 // emit a NOP after it.
1930 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
1931 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1932
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001933 if ((Inst.getOpcode() == Mips::JalOneReg ||
1934 Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
1935 isPicAndNotNxxAbi()) {
1936 if (IsCpRestoreSet) {
1937 // We need a NOP between the JALR and the LW:
1938 // If .set reorder has been used, we've already emitted a NOP.
1939 // If .set noreorder has been used, we need to emit a NOP at this point.
1940 if (!AssemblerOptions.back()->isReorder())
1941 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1942
1943 // Load the $gp from the stack.
1944 SmallVector<MCInst, 3> LoadInsts;
1945 createCpRestoreMemOp(true /*IsLoad*/, CpRestoreOffset /*StackOffset*/,
1946 IDLoc, LoadInsts);
1947
1948 for (const MCInst &Inst : LoadInsts)
1949 Instructions.push_back(Inst);
1950
1951 } else
1952 Warning(IDLoc, "no .cprestore used in PIC mode");
1953 }
1954
Jack Carter9e65aa32013-03-22 00:05:30 +00001955 return false;
1956}
1957
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001958MipsAsmParser::MacroExpanderResultTy
1959MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
1960 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001961 switch (Inst.getOpcode()) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001962 default:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001963 return MER_NotAMacro;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001964 case Mips::LoadImm32:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001965 return expandLoadImm(Inst, true, IDLoc, Instructions) ? MER_Fail
1966 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001967 case Mips::LoadImm64:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001968 return expandLoadImm(Inst, false, IDLoc, Instructions) ? MER_Fail
1969 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001970 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001971 case Mips::LoadAddrImm64:
1972 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1973 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
1974 "expected immediate operand kind");
1975
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001976 return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,
1977 Inst.getOperand(1),
1978 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,
1979 Instructions)
1980 ? MER_Fail
1981 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001982 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001983 case Mips::LoadAddrReg64:
1984 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1985 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1986 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
1987 "expected immediate operand kind");
1988
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001989 return expandLoadAddress(Inst.getOperand(0).getReg(),
1990 Inst.getOperand(1).getReg(), Inst.getOperand(2),
1991 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,
1992 Instructions)
1993 ? MER_Fail
1994 : MER_Success;
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001995 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001996 case Mips::B_MMR6_Pseudo:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001997 return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions) ? MER_Fail
1998 : MER_Success;
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001999 case Mips::SWM_MM:
2000 case Mips::LWM_MM:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002001 return expandLoadStoreMultiple(Inst, IDLoc, Instructions) ? MER_Fail
2002 : MER_Success;
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002003 case Mips::JalOneReg:
2004 case Mips::JalTwoReg:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002005 return expandJalWithRegs(Inst, IDLoc, Instructions) ? MER_Fail
2006 : MER_Success;
Toma Tabacue1e460d2015-06-11 10:36:10 +00002007 case Mips::BneImm:
2008 case Mips::BeqImm:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002009 return expandBranchImm(Inst, IDLoc, Instructions) ? MER_Fail : MER_Success;
Toma Tabacu1a108322015-06-17 13:20:24 +00002010 case Mips::BLT:
2011 case Mips::BLE:
2012 case Mips::BGE:
2013 case Mips::BGT:
2014 case Mips::BLTU:
2015 case Mips::BLEU:
2016 case Mips::BGEU:
2017 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002018 case Mips::BLTL:
2019 case Mips::BLEL:
2020 case Mips::BGEL:
2021 case Mips::BGTL:
2022 case Mips::BLTUL:
2023 case Mips::BLEUL:
2024 case Mips::BGEUL:
2025 case Mips::BGTUL:
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002026 case Mips::BLTImmMacro:
2027 case Mips::BLEImmMacro:
2028 case Mips::BGEImmMacro:
2029 case Mips::BGTImmMacro:
2030 case Mips::BLTUImmMacro:
2031 case Mips::BLEUImmMacro:
2032 case Mips::BGEUImmMacro:
2033 case Mips::BGTUImmMacro:
2034 case Mips::BLTLImmMacro:
2035 case Mips::BLELImmMacro:
2036 case Mips::BGELImmMacro:
2037 case Mips::BGTLImmMacro:
2038 case Mips::BLTULImmMacro:
2039 case Mips::BLEULImmMacro:
2040 case Mips::BGEULImmMacro:
2041 case Mips::BGTULImmMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002042 return expandCondBranches(Inst, IDLoc, Instructions) ? MER_Fail
2043 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002044 case Mips::SDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002045 return expandDiv(Inst, IDLoc, Instructions, false, true) ? MER_Fail
2046 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002047 case Mips::DSDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002048 return expandDiv(Inst, IDLoc, Instructions, true, true) ? MER_Fail
2049 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002050 case Mips::UDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002051 return expandDiv(Inst, IDLoc, Instructions, false, false) ? MER_Fail
2052 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002053 case Mips::DUDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002054 return expandDiv(Inst, IDLoc, Instructions, true, false) ? MER_Fail
2055 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002056 case Mips::PseudoTRUNC_W_S:
2057 return expandTrunc(Inst, false, false, IDLoc, Instructions) ? MER_Fail
2058 : MER_Success;
2059 case Mips::PseudoTRUNC_W_D32:
2060 return expandTrunc(Inst, true, false, IDLoc, Instructions) ? MER_Fail
2061 : MER_Success;
2062 case Mips::PseudoTRUNC_W_D:
2063 return expandTrunc(Inst, true, true, IDLoc, Instructions) ? MER_Fail
2064 : MER_Success;
Daniel Sanders6394ee52015-10-15 14:52:58 +00002065 case Mips::Ulh:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002066 return expandUlh(Inst, true, IDLoc, Instructions) ? MER_Fail : MER_Success;
Toma Tabacud88d79c2015-06-23 14:39:42 +00002067 case Mips::Ulhu:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002068 return expandUlh(Inst, false, IDLoc, Instructions) ? MER_Fail : MER_Success;
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00002069 case Mips::Ulw:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002070 return expandUlw(Inst, IDLoc, Instructions) ? MER_Fail : MER_Success;
2071 case Mips::NORImm:
2072 return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail
2073 : MER_Success;
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002074 case Mips::ADDi:
2075 case Mips::ADDiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002076 case Mips::SLTi:
2077 case Mips::SLTiu:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002078 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2079 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2080 int64_t ImmValue = Inst.getOperand(2).getImm();
2081 if (isInt<16>(ImmValue))
2082 return MER_NotAMacro;
2083 return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail
2084 : MER_Success;
2085 }
2086 return MER_NotAMacro;
2087 case Mips::ANDi:
2088 case Mips::ORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002089 case Mips::XORi:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002090 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2091 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2092 int64_t ImmValue = Inst.getOperand(2).getImm();
2093 if (isUInt<16>(ImmValue))
2094 return MER_NotAMacro;
2095 return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail
2096 : MER_Success;
2097 }
2098 return MER_NotAMacro;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002099 case Mips::ROL:
2100 case Mips::ROR:
2101 return expandRotation(Inst, IDLoc, Instructions) ? MER_Fail
2102 : MER_Success;
2103 case Mips::ROLImm:
2104 case Mips::RORImm:
2105 return expandRotationImm(Inst, IDLoc, Instructions) ? MER_Fail
2106 : MER_Success;
2107 case Mips::DROL:
2108 case Mips::DROR:
2109 return expandDRotation(Inst, IDLoc, Instructions) ? MER_Fail
2110 : MER_Success;
2111 case Mips::DROLImm:
2112 case Mips::DRORImm:
2113 return expandDRotationImm(Inst, IDLoc, Instructions) ? MER_Fail
2114 : MER_Success;
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00002115 case Mips::ABSMacro:
2116 return expandAbs(Inst, IDLoc, Instructions) ? MER_Fail
2117 : MER_Success;
Jack Carterd0bd6422013-04-18 00:41:53 +00002118 }
Jack Carter30a59822012-10-04 04:03:53 +00002119}
Jack Carter92995f12012-10-06 00:53:28 +00002120
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002121bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
2122 SmallVectorImpl<MCInst> &Instructions) {
2123 // Create a JALR instruction which is going to replace the pseudo-JAL.
2124 MCInst JalrInst;
2125 JalrInst.setLoc(IDLoc);
2126 const MCOperand FirstRegOp = Inst.getOperand(0);
2127 const unsigned Opcode = Inst.getOpcode();
2128
2129 if (Opcode == Mips::JalOneReg) {
2130 // jal $rs => jalr $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002131 if (IsCpRestoreSet && inMicroMipsMode()) {
2132 JalrInst.setOpcode(Mips::JALRS16_MM);
2133 JalrInst.addOperand(FirstRegOp);
2134 } else if (inMicroMipsMode()) {
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002135 JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002136 JalrInst.addOperand(FirstRegOp);
2137 } else {
2138 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002139 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002140 JalrInst.addOperand(FirstRegOp);
2141 }
2142 } else if (Opcode == Mips::JalTwoReg) {
2143 // jal $rd, $rs => jalr $rd, $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002144 if (IsCpRestoreSet && inMicroMipsMode())
2145 JalrInst.setOpcode(Mips::JALRS_MM);
2146 else
2147 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002148 JalrInst.addOperand(FirstRegOp);
2149 const MCOperand SecondRegOp = Inst.getOperand(1);
2150 JalrInst.addOperand(SecondRegOp);
2151 }
2152 Instructions.push_back(JalrInst);
2153
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002154 // If .set reorder is active and branch instruction has a delay slot,
2155 // emit a NOP after it.
2156 const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
2157 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) {
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002158 createNop(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc, Instructions);
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002159 }
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002160
2161 return false;
2162}
2163
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002164/// Can the value be represented by a unsigned N-bit value and a shift left?
Benjamin Kramer039b1042015-10-28 13:54:36 +00002165template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002166 unsigned BitNum = findFirstSet(x);
2167
2168 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2169}
2170
2171/// Load (or add) an immediate into a register.
2172///
2173/// @param ImmValue The immediate to load.
2174/// @param DstReg The register that will hold the immediate.
2175/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2176/// for a simple initialization.
2177/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2178/// @param IsAddress True if the immediate represents an address. False if it
2179/// is an integer.
2180/// @param IDLoc Location of the immediate in the source file.
2181/// @param Instructions The instructions emitted by this expansion.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002182bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002183 unsigned SrcReg, bool Is32BitImm,
2184 bool IsAddress, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00002185 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu00e98672015-05-01 12:19:27 +00002186 if (!Is32BitImm && !isGP64bit()) {
2187 Error(IDLoc, "instruction requires a 64-bit architecture");
2188 return true;
2189 }
2190
Daniel Sanders03f9c012015-07-14 12:24:22 +00002191 if (Is32BitImm) {
2192 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2193 // Sign extend up to 64-bit so that the predicates match the hardware
2194 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2195 // true.
2196 ImmValue = SignExtend64<32>(ImmValue);
2197 } else {
2198 Error(IDLoc, "instruction requires a 32-bit immediate");
2199 return true;
2200 }
2201 }
2202
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002203 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2204 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2205
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002206 bool UseSrcReg = false;
2207 if (SrcReg != Mips::NoRegister)
2208 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002209
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002210 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002211 if (UseSrcReg &&
2212 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002213 // At this point we need AT to perform the expansions and we exit if it is
2214 // not available.
2215 unsigned ATReg = getATReg(IDLoc);
2216 if (!ATReg)
2217 return true;
2218 TmpReg = ATReg;
2219 }
2220
Daniel Sanders03f9c012015-07-14 12:24:22 +00002221 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002222 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002223 SrcReg = ZeroReg;
2224
2225 // This doesn't quite follow the usual ABI expectations for N32 but matches
2226 // traditional assembler behaviour. N32 would normally use addiu for both
2227 // integers and addresses.
2228 if (IsAddress && !Is32BitImm) {
2229 emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
2230 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002231 }
2232
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002233 emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
2234 return false;
2235 }
2236
2237 if (isUInt<16>(ImmValue)) {
2238 unsigned TmpReg = DstReg;
2239 if (SrcReg == DstReg) {
2240 TmpReg = getATReg(IDLoc);
2241 if (!TmpReg)
2242 return true;
2243 }
2244
2245 emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002246 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002247 emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2248 return false;
2249 }
2250
2251 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002252 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002253
Toma Tabacu79588102015-04-29 10:19:56 +00002254 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2255 uint16_t Bits15To0 = ImmValue & 0xffff;
2256
Toma Tabacua3d056f2015-05-15 09:42:11 +00002257 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002258 // Traditional behaviour seems to special case this particular value. It's
2259 // not clear why other masks are handled differently.
2260 if (ImmValue == 0xffffffff) {
Daniel Sandersf1ae3672015-08-18 09:55:57 +00002261 emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, Instructions);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002262 emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, Instructions);
2263 if (UseSrcReg)
2264 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2265 return false;
2266 }
2267
2268 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002269 // upper 32 bits.
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002270 emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002271 emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, Instructions);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002272 if (Bits15To0)
2273 emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
2274 if (UseSrcReg)
2275 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2276 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002277 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002278
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002279 emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, Instructions);
2280 if (Bits15To0)
2281 emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002282 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002283 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2284 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002285 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002286
2287 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2288 if (Is32BitImm) {
2289 Error(IDLoc, "instruction requires a 32-bit immediate");
2290 return true;
2291 }
2292
2293 // Traditionally, these immediates are shifted as little as possible and as
2294 // such we align the most significant bit to bit 15 of our temporary.
2295 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2296 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2297 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2298 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
2299 emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, Instructions);
2300 emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, Instructions);
2301
2302 if (UseSrcReg)
2303 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2304
2305 return false;
2306 }
2307
2308 warnIfNoMacro(IDLoc);
2309
2310 // The remaining case is packed with a sequence of dsll and ori with zeros
2311 // being omitted and any neighbouring dsll's being coalesced.
2312 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2313
2314 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2315 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
2316 IDLoc, Instructions))
2317 return false;
2318
2319 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2320 // skip it and defer the shift to the next chunk.
2321 unsigned ShiftCarriedForwards = 16;
2322 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2323 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2324
2325 if (ImmChunk != 0) {
2326 emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
2327 Instructions);
2328 emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, Instructions);
2329 ShiftCarriedForwards = 0;
2330 }
2331
2332 ShiftCarriedForwards += 16;
2333 }
2334 ShiftCarriedForwards -= 16;
2335
2336 // Finish any remaining shifts left by trailing zeros.
2337 if (ShiftCarriedForwards)
2338 emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
2339 Instructions);
2340
2341 if (UseSrcReg)
2342 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2343
Matheus Almeida3813d572014-06-19 14:39:14 +00002344 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002345}
Jack Carter92995f12012-10-06 00:53:28 +00002346
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002347bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
2348 SmallVectorImpl<MCInst> &Instructions) {
2349 const MCOperand &ImmOp = Inst.getOperand(1);
2350 assert(ImmOp.isImm() && "expected immediate operand kind");
2351 const MCOperand &DstRegOp = Inst.getOperand(0);
2352 assert(DstRegOp.isReg() && "expected register operand kind");
2353
2354 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002355 Is32BitImm, false, IDLoc, Instructions))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002356 return true;
2357
2358 return false;
2359}
2360
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002361bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2362 const MCOperand &Offset,
2363 bool Is32BitAddress, SMLoc IDLoc,
2364 SmallVectorImpl<MCInst> &Instructions) {
2365 // la can't produce a usable address when addresses are 64-bit.
2366 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2367 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2368 // We currently can't do this because we depend on the equality
2369 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2370 Error(IDLoc, "la used to load 64-bit address");
2371 // Continue as if we had 'dla' instead.
2372 Is32BitAddress = false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002373 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002374
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002375 // dla requires 64-bit addresses.
Scott Egerton24557012016-01-21 15:11:01 +00002376 if (!Is32BitAddress && !hasMips3()) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002377 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002378 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002379 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002380
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002381 if (!Offset.isImm())
2382 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
2383 Is32BitAddress, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002384
Scott Egerton24557012016-01-21 15:11:01 +00002385 if (!ABI.ArePtrs64bit()) {
2386 // Continue as if we had 'la' whether we had 'la' or 'dla'.
2387 Is32BitAddress = true;
2388 }
2389
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002390 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
2391 IDLoc, Instructions);
Jack Carter543fdf82012-10-09 23:29:45 +00002392}
2393
Toma Tabacuf712ede2015-06-17 14:31:51 +00002394bool MipsAsmParser::loadAndAddSymbolAddress(
2395 const MCExpr *SymExpr, unsigned DstReg, unsigned SrcReg, bool Is32BitSym,
2396 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002397 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002398
Daniel Sandersd5a89412015-10-05 13:19:29 +00002399 const MCExpr *Symbol = cast<MCExpr>(SymExpr);
2400 const MipsMCExpr *HiExpr = MipsMCExpr::create(
2401 MCSymbolRefExpr::VK_Mips_ABS_HI, Symbol, getContext());
2402 const MipsMCExpr *LoExpr = MipsMCExpr::create(
2403 MCSymbolRefExpr::VK_Mips_ABS_LO, Symbol, getContext());
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002404
Toma Tabacufb9d1252015-06-22 12:08:39 +00002405 bool UseSrcReg = SrcReg != Mips::NoRegister;
2406
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002407 // This is the 64-bit symbol address expansion.
2408 if (ABI.ArePtrs64bit() && isGP64bit()) {
2409 // We always need AT for the 64-bit expansion.
2410 // If it is not available we exit.
2411 unsigned ATReg = getATReg(IDLoc);
2412 if (!ATReg)
2413 return true;
2414
Daniel Sandersd5a89412015-10-05 13:19:29 +00002415 const MipsMCExpr *HighestExpr = MipsMCExpr::create(
2416 MCSymbolRefExpr::VK_Mips_HIGHEST, Symbol, getContext());
2417 const MipsMCExpr *HigherExpr = MipsMCExpr::create(
2418 MCSymbolRefExpr::VK_Mips_HIGHER, Symbol, getContext());
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002419
Scott Egerton24557012016-01-21 15:11:01 +00002420 if (UseSrcReg &&
2421 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2422 SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002423 // If $rs is the same as $rd:
2424 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
2425 // daddiu $at, $at, %higher(sym)
2426 // dsll $at, $at, 16
2427 // daddiu $at, $at, %hi(sym)
2428 // dsll $at, $at, 16
2429 // daddiu $at, $at, %lo(sym)
2430 // daddu $rd, $at, $rd
2431 emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
2432 Instructions);
2433 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HigherExpr),
2434 IDLoc, Instructions);
2435 emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
2436 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
2437 Instructions);
2438 emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
2439 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
2440 Instructions);
2441 emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, Instructions);
2442
2443 return false;
2444 }
2445
2446 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2447 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
2448 // lui $at, %hi(sym)
2449 // daddiu $rd, $rd, %higher(sym)
2450 // daddiu $at, $at, %lo(sym)
2451 // dsll32 $rd, $rd, 0
2452 // daddu $rd, $rd, $at
2453 // (daddu $rd, $rd, $rs)
2454 emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
2455 Instructions);
2456 emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
2457 Instructions);
2458 emitRRX(Mips::DADDiu, DstReg, DstReg, MCOperand::createExpr(HigherExpr),
2459 IDLoc, Instructions);
2460 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
2461 Instructions);
2462 emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, Instructions);
2463 emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, Instructions);
2464 if (UseSrcReg)
2465 emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, Instructions);
2466
2467 return false;
2468 }
2469
2470 // And now, the 32-bit symbol address expansion:
2471 // If $rs is the same as $rd:
2472 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
2473 // ori $at, $at, %lo(sym)
2474 // addu $rd, $at, $rd
2475 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2476 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
2477 // ori $rd, $rd, %lo(sym)
2478 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00002479 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002480 if (UseSrcReg &&
2481 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002482 // If $rs is the same as $rd, we need to use AT.
2483 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00002484 unsigned ATReg = getATReg(IDLoc);
2485 if (!ATReg)
2486 return true;
2487 TmpReg = ATReg;
2488 }
2489
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002490 emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, Instructions);
2491 emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr), IDLoc,
2492 Instructions);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002493
Toma Tabacufb9d1252015-06-22 12:08:39 +00002494 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002495 emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2496 else
Scott Egerton24557012016-01-21 15:11:01 +00002497 assert(
2498 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, TmpReg));
Toma Tabacuf712ede2015-06-17 14:31:51 +00002499
Toma Tabacu674825c2015-06-16 12:16:24 +00002500 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002501}
2502
NAKAMURA Takumi2bbc90c2015-01-23 01:02:07 +00002503bool MipsAsmParser::expandUncondBranchMMPseudo(
2504 MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00002505 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
2506 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002507
2508 MCOperand Offset = Inst.getOperand(0);
2509 if (Offset.isExpr()) {
2510 Inst.clear();
2511 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002512 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2513 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2514 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002515 } else {
2516 assert(Offset.isImm() && "expected immediate operand kind");
Craig Topper55b1f292015-10-10 20:17:07 +00002517 if (isInt<11>(Offset.getImm())) {
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002518 // If offset fits into 11 bits then this instruction becomes microMIPS
2519 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00002520 if (inMicroMipsMode())
2521 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002522 } else {
Craig Topper55b1f292015-10-10 20:17:07 +00002523 if (!isInt<17>(Offset.getImm()))
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002524 Error(IDLoc, "branch target out of range");
2525 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
2526 Error(IDLoc, "branch to misaligned address");
2527 Inst.clear();
2528 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002529 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2530 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2531 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002532 }
2533 }
2534 Instructions.push_back(Inst);
2535
Zoran Jovanovicada70912015-09-07 11:56:37 +00002536 // If .set reorder is active and branch instruction has a delay slot,
2537 // emit a NOP after it.
2538 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
2539 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Toma Tabacu234482a2015-03-16 12:03:39 +00002540 createNop(true, IDLoc, Instructions);
2541
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002542 return false;
2543}
2544
Toma Tabacue1e460d2015-06-11 10:36:10 +00002545bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc,
2546 SmallVectorImpl<MCInst> &Instructions) {
2547 const MCOperand &DstRegOp = Inst.getOperand(0);
2548 assert(DstRegOp.isReg() && "expected register operand kind");
2549
2550 const MCOperand &ImmOp = Inst.getOperand(1);
2551 assert(ImmOp.isImm() && "expected immediate operand kind");
2552
2553 const MCOperand &MemOffsetOp = Inst.getOperand(2);
Daniel Sanders90f0d0b2016-02-29 11:24:49 +00002554 assert((MemOffsetOp.isImm() || MemOffsetOp.isExpr()) &&
2555 "expected immediate or expression operand");
Toma Tabacue1e460d2015-06-11 10:36:10 +00002556
2557 unsigned OpCode = 0;
2558 switch(Inst.getOpcode()) {
2559 case Mips::BneImm:
2560 OpCode = Mips::BNE;
2561 break;
2562 case Mips::BeqImm:
2563 OpCode = Mips::BEQ;
2564 break;
2565 default:
2566 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
2567 break;
2568 }
2569
2570 int64_t ImmValue = ImmOp.getImm();
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002571 if (ImmValue == 0)
2572 emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
2573 Instructions);
2574 else {
Toma Tabacue1e460d2015-06-11 10:36:10 +00002575 warnIfNoMacro(IDLoc);
2576
2577 unsigned ATReg = getATReg(IDLoc);
2578 if (!ATReg)
2579 return true;
2580
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002581 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
2582 IDLoc, Instructions))
Toma Tabacue1e460d2015-06-11 10:36:10 +00002583 return true;
2584
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002585 emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, Instructions);
Toma Tabacue1e460d2015-06-11 10:36:10 +00002586 }
2587 return false;
2588}
2589
Jack Carter9e65aa32013-03-22 00:05:30 +00002590void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00002591 SmallVectorImpl<MCInst> &Instructions,
2592 bool isLoad, bool isImmOpnd) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002593 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00002594 const MCExpr *ExprOffset;
2595 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00002596 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002597 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2598 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002599 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002600 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2601 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002602 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00002603 if (isImmOpnd) {
2604 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
2605 ImmOffset = Inst.getOperand(2).getImm();
2606 LoOffset = ImmOffset & 0x0000ffff;
2607 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00002608 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00002609 if (LoOffset & 0x8000)
2610 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00002611 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00002612 ExprOffset = Inst.getOperand(2).getExpr();
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002613 // These are some of the types of expansions we perform here:
2614 // 1) lw $8, sym => lui $8, %hi(sym)
2615 // lw $8, %lo(sym)($8)
2616 // 2) lw $8, offset($9) => lui $8, %hi(offset)
2617 // add $8, $8, $9
2618 // lw $8, %lo(offset)($9)
2619 // 3) lw $8, offset($8) => lui $at, %hi(offset)
2620 // add $at, $at, $8
2621 // lw $8, %lo(offset)($at)
2622 // 4) sw $8, sym => lui $at, %hi(sym)
2623 // sw $8, %lo(sym)($at)
2624 // 5) sw $8, offset($8) => lui $at, %hi(offset)
2625 // add $at, $at, $8
2626 // sw $8, %lo(offset)($at)
2627 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
2628 // ldc1 $f0, %lo(sym)($at)
2629 //
2630 // For load instructions we can use the destination register as a temporary
2631 // if base and dst are different (examples 1 and 2) and if the base register
2632 // is general purpose otherwise we must use $at (example 6) and error if it's
2633 // not available. For stores we must use $at (examples 4 and 5) because we
2634 // must not clobber the source register setting up the offset.
2635 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
2636 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
2637 unsigned RegClassIDOp0 =
2638 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
2639 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
2640 (RegClassIDOp0 == Mips::GPR64RegClassID);
2641 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00002642 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002643 else {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002644 // At this point we need AT to perform the expansions and we exit if it is
2645 // not available.
Toma Tabacu89a712b2015-04-15 10:48:56 +00002646 TmpRegNum = getATReg(IDLoc);
2647 if (!TmpRegNum)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002648 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002649 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002650
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002651 emitRX(Mips::LUi, TmpRegNum,
2652 isImmOpnd ? MCOperand::createImm(HiOffset)
2653 : MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "hi")),
2654 IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00002655 // Add temp register to base.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002656 if (BaseRegNum != Mips::ZERO)
2657 emitRRR(Mips::ADDu, TmpRegNum, TmpRegNum, BaseRegNum, IDLoc, Instructions);
Alp Tokercb402912014-01-24 17:20:08 +00002658 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00002659 // of offset and new base.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002660 emitRRX(Inst.getOpcode(), RegOpNum, TmpRegNum,
2661 isImmOpnd
2662 ? MCOperand::createImm(LoOffset)
2663 : MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "lo")),
2664 IDLoc, Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +00002665}
2666
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002667bool
2668MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2669 SmallVectorImpl<MCInst> &Instructions) {
2670 unsigned OpNum = Inst.getNumOperands();
2671 unsigned Opcode = Inst.getOpcode();
2672 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2673
2674 assert (Inst.getOperand(OpNum - 1).isImm() &&
2675 Inst.getOperand(OpNum - 2).isReg() &&
2676 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2677
2678 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2679 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002680 (Inst.getOperand(OpNum - 2).getReg() == Mips::SP ||
2681 Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) &&
2682 (Inst.getOperand(OpNum - 3).getReg() == Mips::RA ||
2683 Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002684 // It can be implemented as SWM16 or LWM16 instruction.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002685 if (inMicroMipsMode() && hasMips32r6())
2686 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6;
2687 else
2688 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2689 }
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002690
2691 Inst.setOpcode(NewOpcode);
2692 Instructions.push_back(Inst);
2693 return false;
2694}
2695
Toma Tabacu1a108322015-06-17 13:20:24 +00002696bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
2697 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002698 bool EmittedNoMacroWarning = false;
Toma Tabacu1a108322015-06-17 13:20:24 +00002699 unsigned PseudoOpcode = Inst.getOpcode();
2700 unsigned SrcReg = Inst.getOperand(0).getReg();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002701 const MCOperand &TrgOp = Inst.getOperand(1);
Toma Tabacu1a108322015-06-17 13:20:24 +00002702 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
2703
2704 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002705 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00002706
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002707 unsigned TrgReg;
2708 if (TrgOp.isReg())
2709 TrgReg = TrgOp.getReg();
2710 else if (TrgOp.isImm()) {
2711 warnIfNoMacro(IDLoc);
2712 EmittedNoMacroWarning = true;
2713
2714 TrgReg = getATReg(IDLoc);
2715 if (!TrgReg)
2716 return true;
2717
2718 switch(PseudoOpcode) {
2719 default:
2720 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2721 case Mips::BLTImmMacro:
2722 PseudoOpcode = Mips::BLT;
2723 break;
2724 case Mips::BLEImmMacro:
2725 PseudoOpcode = Mips::BLE;
2726 break;
2727 case Mips::BGEImmMacro:
2728 PseudoOpcode = Mips::BGE;
2729 break;
2730 case Mips::BGTImmMacro:
2731 PseudoOpcode = Mips::BGT;
2732 break;
2733 case Mips::BLTUImmMacro:
2734 PseudoOpcode = Mips::BLTU;
2735 break;
2736 case Mips::BLEUImmMacro:
2737 PseudoOpcode = Mips::BLEU;
2738 break;
2739 case Mips::BGEUImmMacro:
2740 PseudoOpcode = Mips::BGEU;
2741 break;
2742 case Mips::BGTUImmMacro:
2743 PseudoOpcode = Mips::BGTU;
2744 break;
2745 case Mips::BLTLImmMacro:
2746 PseudoOpcode = Mips::BLTL;
2747 break;
2748 case Mips::BLELImmMacro:
2749 PseudoOpcode = Mips::BLEL;
2750 break;
2751 case Mips::BGELImmMacro:
2752 PseudoOpcode = Mips::BGEL;
2753 break;
2754 case Mips::BGTLImmMacro:
2755 PseudoOpcode = Mips::BGTL;
2756 break;
2757 case Mips::BLTULImmMacro:
2758 PseudoOpcode = Mips::BLTUL;
2759 break;
2760 case Mips::BLEULImmMacro:
2761 PseudoOpcode = Mips::BLEUL;
2762 break;
2763 case Mips::BGEULImmMacro:
2764 PseudoOpcode = Mips::BGEUL;
2765 break;
2766 case Mips::BGTULImmMacro:
2767 PseudoOpcode = Mips::BGTUL;
2768 break;
2769 }
2770
2771 if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
2772 false, IDLoc, Instructions))
2773 return true;
2774 }
2775
Toma Tabacu1a108322015-06-17 13:20:24 +00002776 switch (PseudoOpcode) {
2777 case Mips::BLT:
2778 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002779 case Mips::BLTL:
2780 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002781 AcceptsEquality = false;
2782 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002783 IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
2784 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002785 ZeroSrcOpcode = Mips::BGTZ;
2786 ZeroTrgOpcode = Mips::BLTZ;
2787 break;
2788 case Mips::BLE:
2789 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002790 case Mips::BLEL:
2791 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002792 AcceptsEquality = true;
2793 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002794 IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
2795 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002796 ZeroSrcOpcode = Mips::BGEZ;
2797 ZeroTrgOpcode = Mips::BLEZ;
2798 break;
2799 case Mips::BGE:
2800 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002801 case Mips::BGEL:
2802 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002803 AcceptsEquality = true;
2804 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002805 IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
2806 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002807 ZeroSrcOpcode = Mips::BLEZ;
2808 ZeroTrgOpcode = Mips::BGEZ;
2809 break;
2810 case Mips::BGT:
2811 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002812 case Mips::BGTL:
2813 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002814 AcceptsEquality = false;
2815 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002816 IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
2817 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002818 ZeroSrcOpcode = Mips::BLTZ;
2819 ZeroTrgOpcode = Mips::BGTZ;
2820 break;
2821 default:
2822 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2823 }
2824
Toma Tabacu1a108322015-06-17 13:20:24 +00002825 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
2826 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
2827 if (IsSrcRegZero && IsTrgRegZero) {
2828 // FIXME: All of these Opcode-specific if's are needed for compatibility
2829 // with GAS' behaviour. However, they may not generate the most efficient
2830 // code in some circumstances.
2831 if (PseudoOpcode == Mips::BLT) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002832 emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2833 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002834 return false;
2835 }
2836 if (PseudoOpcode == Mips::BLE) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002837 emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2838 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002839 Warning(IDLoc, "branch is always taken");
2840 return false;
2841 }
2842 if (PseudoOpcode == Mips::BGE) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002843 emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2844 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002845 Warning(IDLoc, "branch is always taken");
2846 return false;
2847 }
2848 if (PseudoOpcode == Mips::BGT) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002849 emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2850 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002851 return false;
2852 }
2853 if (PseudoOpcode == Mips::BGTU) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002854 emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
2855 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002856 return false;
2857 }
2858 if (AcceptsEquality) {
2859 // If both registers are $0 and the pseudo-branch accepts equality, it
2860 // will always be taken, so we emit an unconditional branch.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002861 emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
2862 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002863 Warning(IDLoc, "branch is always taken");
2864 return false;
2865 }
2866 // If both registers are $0 and the pseudo-branch does not accept
2867 // equality, it will never be taken, so we don't have to emit anything.
2868 return false;
2869 }
2870 if (IsSrcRegZero || IsTrgRegZero) {
2871 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
2872 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
2873 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
2874 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
2875 // the pseudo-branch will never be taken, so we don't emit anything.
2876 // This only applies to unsigned pseudo-branches.
2877 return false;
2878 }
2879 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
2880 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
2881 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
2882 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
2883 // the pseudo-branch will always be taken, so we emit an unconditional
2884 // branch.
2885 // This only applies to unsigned pseudo-branches.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002886 emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
2887 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002888 Warning(IDLoc, "branch is always taken");
2889 return false;
2890 }
2891 if (IsUnsigned) {
2892 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
2893 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
2894 // the pseudo-branch will be taken only when the non-zero register is
2895 // different from 0, so we emit a BNEZ.
2896 //
2897 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
2898 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
2899 // the pseudo-branch will be taken only when the non-zero register is
2900 // equal to 0, so we emit a BEQZ.
2901 //
2902 // Because only BLEU and BGEU branch on equality, we can use the
2903 // AcceptsEquality variable to decide when to emit the BEQZ.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002904 emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
2905 IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
2906 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002907 return false;
2908 }
2909 // If we have a signed pseudo-branch and one of the registers is $0,
2910 // we can use an appropriate compare-to-zero branch. We select which one
2911 // to use in the switch statement above.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002912 emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
2913 IsSrcRegZero ? TrgReg : SrcReg, MCOperand::createExpr(OffsetExpr),
2914 IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002915 return false;
2916 }
2917
2918 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
2919 // expansions. If it is not available, we return.
2920 unsigned ATRegNum = getATReg(IDLoc);
2921 if (!ATRegNum)
2922 return true;
2923
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002924 if (!EmittedNoMacroWarning)
2925 warnIfNoMacro(IDLoc);
Toma Tabacu1a108322015-06-17 13:20:24 +00002926
2927 // SLT fits well with 2 of our 4 pseudo-branches:
2928 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
2929 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
2930 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
2931 // This is accomplished by using a BNEZ with the result of the SLT.
2932 //
2933 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
2934 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
2935 // Because only BGE and BLE branch on equality, we can use the
2936 // AcceptsEquality variable to decide when to emit the BEQZ.
2937 // Note that the order of the SLT arguments doesn't change between
2938 // opposites.
2939 //
2940 // The same applies to the unsigned variants, except that SLTu is used
2941 // instead of SLT.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002942 emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
2943 ReverseOrderSLT ? TrgReg : SrcReg, ReverseOrderSLT ? SrcReg : TrgReg,
2944 IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002945
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002946 emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
2947 : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
2948 ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2949 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002950 return false;
2951}
2952
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002953bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc,
2954 SmallVectorImpl<MCInst> &Instructions,
2955 const bool IsMips64, const bool Signed) {
2956 if (hasMips32r6()) {
2957 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
2958 return false;
2959 }
2960
2961 warnIfNoMacro(IDLoc);
2962
2963 const MCOperand &RsRegOp = Inst.getOperand(0);
2964 assert(RsRegOp.isReg() && "expected register operand kind");
2965 unsigned RsReg = RsRegOp.getReg();
2966
2967 const MCOperand &RtRegOp = Inst.getOperand(1);
2968 assert(RtRegOp.isReg() && "expected register operand kind");
2969 unsigned RtReg = RtRegOp.getReg();
2970 unsigned DivOp;
2971 unsigned ZeroReg;
2972
2973 if (IsMips64) {
2974 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
2975 ZeroReg = Mips::ZERO_64;
2976 } else {
2977 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
2978 ZeroReg = Mips::ZERO;
2979 }
2980
2981 bool UseTraps = useTraps();
2982
2983 if (RsReg == Mips::ZERO || RsReg == Mips::ZERO_64) {
2984 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)
2985 Warning(IDLoc, "dividing zero by zero");
2986 if (IsMips64) {
2987 if (Signed && (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)) {
2988 if (UseTraps) {
2989 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2990 return false;
2991 }
2992
2993 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2994 return false;
2995 }
2996 } else {
2997 emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
2998 return false;
2999 }
3000 }
3001
3002 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
3003 Warning(IDLoc, "division by zero");
3004 if (Signed) {
3005 if (UseTraps) {
3006 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
3007 return false;
3008 }
3009
3010 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
3011 return false;
3012 }
3013 }
3014
3015 // FIXME: The values for these two BranchTarget variables may be different in
3016 // micromips. These magic numbers need to be removed.
3017 unsigned BranchTargetNoTraps;
3018 unsigned BranchTarget;
3019
3020 if (UseTraps) {
3021 BranchTarget = IsMips64 ? 12 : 8;
3022 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
3023 } else {
3024 BranchTarget = IsMips64 ? 20 : 16;
3025 BranchTargetNoTraps = 8;
3026 // Branch to the li instruction.
3027 emitRRI(Mips::BNE, RtReg, ZeroReg, BranchTargetNoTraps, IDLoc,
3028 Instructions);
3029 }
3030
3031 emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
3032
3033 if (!UseTraps)
3034 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
3035
3036 if (!Signed) {
3037 emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
3038 return false;
3039 }
3040
3041 unsigned ATReg = getATReg(IDLoc);
3042 if (!ATReg)
3043 return true;
3044
3045 emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, Instructions);
3046 if (IsMips64) {
3047 // Branch to the mflo instruction.
3048 emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
3049 emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, Instructions);
3050 emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, Instructions);
3051 } else {
3052 // Branch to the mflo instruction.
3053 emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
3054 emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, Instructions);
3055 }
3056
3057 if (UseTraps)
3058 emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, Instructions);
3059 else {
3060 // Branch to the mflo instruction.
3061 emitRRI(Mips::BNE, RsReg, ATReg, BranchTargetNoTraps, IDLoc, Instructions);
3062 emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, Instructions);
3063 emitII(Mips::BREAK, 0x6, 0, IDLoc, Instructions);
3064 }
3065 emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
3066 return false;
3067}
3068
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003069bool MipsAsmParser::expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU,
3070 SMLoc IDLoc,
3071 SmallVectorImpl<MCInst> &Instructions) {
3072
3073 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
3074 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() &&
3075 Inst.getOperand(2).isReg() && "Invalid instruction operand.");
3076
3077 unsigned FirstReg = Inst.getOperand(0).getReg();
3078 unsigned SecondReg = Inst.getOperand(1).getReg();
3079 unsigned ThirdReg = Inst.getOperand(2).getReg();
3080
3081 if (hasMips1() && !hasMips2()) {
3082 unsigned ATReg = getATReg(IDLoc);
3083 if (!ATReg)
3084 return true;
3085 emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, Instructions);
3086 emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, Instructions);
3087 createNop(false, IDLoc, Instructions);
3088 emitRRI(Mips::ORi, ATReg, ThirdReg, 0x3, IDLoc, Instructions);
3089 emitRRI(Mips::XORi, ATReg, ATReg, 0x2, IDLoc, Instructions);
3090 emitRR(Mips::CTC1, Mips::RA, ATReg, IDLoc, Instructions);
3091 createNop(false, IDLoc, Instructions);
3092 emitRR(IsDouble ? (Is64FPU ? Mips::CVT_W_D64 : Mips::CVT_W_D32)
3093 : Mips::CVT_W_S,
3094 FirstReg, SecondReg, IDLoc, Instructions);
3095 emitRR(Mips::CTC1, Mips::RA, ThirdReg, IDLoc, Instructions);
3096 createNop(false, IDLoc, Instructions);
3097 return false;
3098 }
3099
3100 emitRR(IsDouble ? (Is64FPU ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32)
3101 : Mips::TRUNC_W_S,
3102 FirstReg, SecondReg, IDLoc, Instructions);
3103
3104 return false;
3105}
3106
Daniel Sanders6394ee52015-10-15 14:52:58 +00003107bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
3108 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacud88d79c2015-06-23 14:39:42 +00003109 if (hasMips32r6() || hasMips64r6()) {
3110 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3111 return false;
3112 }
3113
3114 warnIfNoMacro(IDLoc);
3115
3116 const MCOperand &DstRegOp = Inst.getOperand(0);
3117 assert(DstRegOp.isReg() && "expected register operand kind");
3118
3119 const MCOperand &SrcRegOp = Inst.getOperand(1);
3120 assert(SrcRegOp.isReg() && "expected register operand kind");
3121
3122 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3123 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3124
3125 unsigned DstReg = DstRegOp.getReg();
3126 unsigned SrcReg = SrcRegOp.getReg();
3127 int64_t OffsetValue = OffsetImmOp.getImm();
3128
3129 // NOTE: We always need AT for ULHU, as it is always used as the source
3130 // register for one of the LBu's.
3131 unsigned ATReg = getATReg(IDLoc);
3132 if (!ATReg)
3133 return true;
3134
3135 // When the value of offset+1 does not fit in 16 bits, we have to load the
3136 // offset in AT, (D)ADDu the original source register (if there was one), and
3137 // then use AT as the source register for the 2 generated LBu's.
3138 bool LoadedOffsetInAT = false;
3139 if (!isInt<16>(OffsetValue + 1) || !isInt<16>(OffsetValue)) {
3140 LoadedOffsetInAT = true;
3141
3142 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003143 true, IDLoc, Instructions))
Toma Tabacud88d79c2015-06-23 14:39:42 +00003144 return true;
3145
3146 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3147 // because it will make our output more similar to GAS'. For example,
3148 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3149 // instead of just an "ori $1, $9, 32768".
3150 // NOTE: If there is no source register specified in the ULHU, the parser
3151 // will interpret it as $0.
3152 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
3153 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
3154 }
3155
3156 unsigned FirstLbuDstReg = LoadedOffsetInAT ? DstReg : ATReg;
3157 unsigned SecondLbuDstReg = LoadedOffsetInAT ? ATReg : DstReg;
3158 unsigned LbuSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3159
3160 int64_t FirstLbuOffset = 0, SecondLbuOffset = 0;
3161 if (isLittle()) {
3162 FirstLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3163 SecondLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3164 } else {
3165 FirstLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3166 SecondLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3167 }
3168
3169 unsigned SllReg = LoadedOffsetInAT ? DstReg : ATReg;
3170
Daniel Sanders6394ee52015-10-15 14:52:58 +00003171 emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
3172 FirstLbuOffset, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003173
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003174 emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondLbuOffset, IDLoc,
3175 Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003176
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003177 emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003178
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003179 emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003180
3181 return false;
3182}
3183
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003184bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc,
3185 SmallVectorImpl<MCInst> &Instructions) {
3186 if (hasMips32r6() || hasMips64r6()) {
3187 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3188 return false;
3189 }
3190
3191 const MCOperand &DstRegOp = Inst.getOperand(0);
3192 assert(DstRegOp.isReg() && "expected register operand kind");
3193
3194 const MCOperand &SrcRegOp = Inst.getOperand(1);
3195 assert(SrcRegOp.isReg() && "expected register operand kind");
3196
3197 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3198 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3199
3200 unsigned SrcReg = SrcRegOp.getReg();
3201 int64_t OffsetValue = OffsetImmOp.getImm();
3202 unsigned ATReg = 0;
3203
3204 // When the value of offset+3 does not fit in 16 bits, we have to load the
3205 // offset in AT, (D)ADDu the original source register (if there was one), and
3206 // then use AT as the source register for the generated LWL and LWR.
3207 bool LoadedOffsetInAT = false;
3208 if (!isInt<16>(OffsetValue + 3) || !isInt<16>(OffsetValue)) {
3209 ATReg = getATReg(IDLoc);
3210 if (!ATReg)
3211 return true;
3212 LoadedOffsetInAT = true;
3213
3214 warnIfNoMacro(IDLoc);
3215
3216 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003217 true, IDLoc, Instructions))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003218 return true;
3219
3220 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3221 // because it will make our output more similar to GAS'. For example,
3222 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3223 // instead of just an "ori $1, $9, 32768".
3224 // NOTE: If there is no source register specified in the ULW, the parser
3225 // will interpret it as $0.
3226 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
3227 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
3228 }
3229
3230 unsigned FinalSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3231 int64_t LeftLoadOffset = 0, RightLoadOffset = 0;
3232 if (isLittle()) {
3233 LeftLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3234 RightLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3235 } else {
3236 LeftLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3237 RightLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3238 }
3239
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003240 emitRRI(Mips::LWL, DstRegOp.getReg(), FinalSrcReg, LeftLoadOffset, IDLoc,
3241 Instructions);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003242
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003243 emitRRI(Mips::LWR, DstRegOp.getReg(), FinalSrcReg, RightLoadOffset, IDLoc,
3244 Instructions);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003245
3246 return false;
3247}
3248
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003249bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
3250 SmallVectorImpl<MCInst> &Instructions) {
3251
3252 assert (Inst.getNumOperands() == 3 && "Invalid operand count");
3253 assert (Inst.getOperand(0).isReg() &&
3254 Inst.getOperand(1).isReg() &&
3255 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
3256
3257 unsigned ATReg = Mips::NoRegister;
3258 unsigned FinalDstReg = Mips::NoRegister;
3259 unsigned DstReg = Inst.getOperand(0).getReg();
3260 unsigned SrcReg = Inst.getOperand(1).getReg();
3261 int64_t ImmValue = Inst.getOperand(2).getImm();
3262
3263 bool Is32Bit = isInt<32>(ImmValue) || isUInt<32>(ImmValue);
3264
3265 unsigned FinalOpcode = Inst.getOpcode();
3266
3267 if (DstReg == SrcReg) {
3268 ATReg = getATReg(Inst.getLoc());
3269 if (!ATReg)
3270 return true;
3271 FinalDstReg = DstReg;
3272 DstReg = ATReg;
3273 }
3274
3275 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Instructions)) {
3276 switch (FinalOpcode) {
3277 default:
3278 llvm_unreachable("unimplemented expansion");
3279 case (Mips::ADDi):
3280 FinalOpcode = Mips::ADD;
3281 break;
3282 case (Mips::ADDiu):
3283 FinalOpcode = Mips::ADDu;
3284 break;
3285 case (Mips::ANDi):
3286 FinalOpcode = Mips::AND;
3287 break;
3288 case (Mips::NORImm):
3289 FinalOpcode = Mips::NOR;
3290 break;
3291 case (Mips::ORi):
3292 FinalOpcode = Mips::OR;
3293 break;
3294 case (Mips::SLTi):
3295 FinalOpcode = Mips::SLT;
3296 break;
3297 case (Mips::SLTiu):
3298 FinalOpcode = Mips::SLTu;
3299 break;
3300 case (Mips::XORi):
3301 FinalOpcode = Mips::XOR;
3302 break;
3303 }
3304
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003305 if (FinalDstReg == Mips::NoRegister)
3306 emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, Instructions);
3307 else
3308 emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc,
3309 Instructions);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003310 return false;
3311 }
3312 return true;
3313}
3314
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003315bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc,
3316 SmallVectorImpl<MCInst> &Instructions) {
3317 unsigned ATReg = Mips::NoRegister;
3318 unsigned DReg = Inst.getOperand(0).getReg();
3319 unsigned SReg = Inst.getOperand(1).getReg();
3320 unsigned TReg = Inst.getOperand(2).getReg();
3321 unsigned TmpReg = DReg;
3322
3323 unsigned FirstShift = Mips::NOP;
3324 unsigned SecondShift = Mips::NOP;
3325
3326 if (hasMips32r2()) {
3327
3328 if (DReg == SReg) {
3329 TmpReg = getATReg(Inst.getLoc());
3330 if (!TmpReg)
3331 return true;
3332 }
3333
3334 if (Inst.getOpcode() == Mips::ROL) {
3335 emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions);
3336 emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), Instructions);
3337 return false;
3338 }
3339
3340 if (Inst.getOpcode() == Mips::ROR) {
3341 emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), Instructions);
3342 return false;
3343 }
3344
3345 return true;
3346 }
3347
3348 if (hasMips32()) {
3349
3350 switch (Inst.getOpcode()) {
3351 default:
3352 llvm_unreachable("unexpected instruction opcode");
3353 case Mips::ROL:
3354 FirstShift = Mips::SRLV;
3355 SecondShift = Mips::SLLV;
3356 break;
3357 case Mips::ROR:
3358 FirstShift = Mips::SLLV;
3359 SecondShift = Mips::SRLV;
3360 break;
3361 }
3362
3363 ATReg = getATReg(Inst.getLoc());
3364 if (!ATReg)
3365 return true;
3366
3367 emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions);
3368 emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), Instructions);
3369 emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), Instructions);
3370 emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions);
3371
3372 return false;
3373 }
3374
3375 return true;
3376}
3377
3378bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
3379 SmallVectorImpl<MCInst> &Instructions) {
3380
3381 unsigned ATReg = Mips::NoRegister;
3382 unsigned DReg = Inst.getOperand(0).getReg();
3383 unsigned SReg = Inst.getOperand(1).getReg();
3384 int64_t ImmValue = Inst.getOperand(2).getImm();
3385
3386 unsigned FirstShift = Mips::NOP;
3387 unsigned SecondShift = Mips::NOP;
3388
3389 if (hasMips32r2()) {
3390
3391 if (Inst.getOpcode() == Mips::ROLImm) {
3392 uint64_t MaxShift = 32;
3393 uint64_t ShiftValue = ImmValue;
3394 if (ImmValue != 0)
3395 ShiftValue = MaxShift - ImmValue;
3396 emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), Instructions);
3397 return false;
3398 }
3399
3400 if (Inst.getOpcode() == Mips::RORImm) {
3401 emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), Instructions);
3402 return false;
3403 }
3404
3405 return true;
3406 }
3407
3408 if (hasMips32()) {
3409
3410 if (ImmValue == 0) {
3411 emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), Instructions);
3412 return false;
3413 }
3414
3415 switch (Inst.getOpcode()) {
3416 default:
3417 llvm_unreachable("unexpected instruction opcode");
3418 case Mips::ROLImm:
3419 FirstShift = Mips::SLL;
3420 SecondShift = Mips::SRL;
3421 break;
3422 case Mips::RORImm:
3423 FirstShift = Mips::SRL;
3424 SecondShift = Mips::SLL;
3425 break;
3426 }
3427
3428 ATReg = getATReg(Inst.getLoc());
3429 if (!ATReg)
3430 return true;
3431
3432 emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), Instructions);
3433 emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), Instructions);
3434 emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions);
3435
3436 return false;
3437 }
3438
3439 return true;
3440}
3441
3442bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc,
3443 SmallVectorImpl<MCInst> &Instructions) {
3444
3445 unsigned ATReg = Mips::NoRegister;
3446 unsigned DReg = Inst.getOperand(0).getReg();
3447 unsigned SReg = Inst.getOperand(1).getReg();
3448 unsigned TReg = Inst.getOperand(2).getReg();
3449 unsigned TmpReg = DReg;
3450
3451 unsigned FirstShift = Mips::NOP;
3452 unsigned SecondShift = Mips::NOP;
3453
3454 if (hasMips64r2()) {
3455
3456 if (TmpReg == SReg) {
3457 TmpReg = getATReg(Inst.getLoc());
3458 if (!TmpReg)
3459 return true;
3460 }
3461
3462 if (Inst.getOpcode() == Mips::DROL) {
3463 emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions);
3464 emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), Instructions);
3465 return false;
3466 }
3467
3468 if (Inst.getOpcode() == Mips::DROR) {
3469 emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), Instructions);
3470 return false;
3471 }
3472
3473 return true;
3474 }
3475
3476 if (hasMips64()) {
3477
3478 switch (Inst.getOpcode()) {
3479 default:
3480 llvm_unreachable("unexpected instruction opcode");
3481 case Mips::DROL:
3482 FirstShift = Mips::DSRLV;
3483 SecondShift = Mips::DSLLV;
3484 break;
3485 case Mips::DROR:
3486 FirstShift = Mips::DSLLV;
3487 SecondShift = Mips::DSRLV;
3488 break;
3489 }
3490
3491 ATReg = getATReg(Inst.getLoc());
3492 if (!ATReg)
3493 return true;
3494
3495 emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions);
3496 emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), Instructions);
3497 emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), Instructions);
3498 emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions);
3499
3500 return false;
3501 }
3502
3503 return true;
3504}
3505
3506bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
3507 SmallVectorImpl<MCInst> &Instructions) {
3508
3509 unsigned ATReg = Mips::NoRegister;
3510 unsigned DReg = Inst.getOperand(0).getReg();
3511 unsigned SReg = Inst.getOperand(1).getReg();
3512 int64_t ImmValue = Inst.getOperand(2).getImm() % 64;
3513
3514 unsigned FirstShift = Mips::NOP;
3515 unsigned SecondShift = Mips::NOP;
3516
3517 MCInst TmpInst;
3518
3519 if (hasMips64r2()) {
3520
3521 unsigned FinalOpcode = Mips::NOP;
3522 if (ImmValue == 0)
3523 FinalOpcode = Mips::DROTR;
3524 else if (ImmValue % 32 == 0)
3525 FinalOpcode = Mips::DROTR32;
3526 else if ((ImmValue >= 1) && (ImmValue <= 32)) {
3527 if (Inst.getOpcode() == Mips::DROLImm)
3528 FinalOpcode = Mips::DROTR32;
3529 else
3530 FinalOpcode = Mips::DROTR;
3531 } else if (ImmValue >= 33) {
3532 if (Inst.getOpcode() == Mips::DROLImm)
3533 FinalOpcode = Mips::DROTR;
3534 else
3535 FinalOpcode = Mips::DROTR32;
3536 }
3537
3538 uint64_t ShiftValue = ImmValue % 32;
3539 if (Inst.getOpcode() == Mips::DROLImm)
3540 ShiftValue = (32 - ImmValue % 32) % 32;
3541
3542 emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), Instructions);
3543
3544 return false;
3545 }
3546
3547 if (hasMips64()) {
3548
3549 if (ImmValue == 0) {
3550 emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), Instructions);
3551 return false;
3552 }
3553
3554 switch (Inst.getOpcode()) {
3555 default:
3556 llvm_unreachable("unexpected instruction opcode");
3557 case Mips::DROLImm:
3558 if ((ImmValue >= 1) && (ImmValue <= 31)) {
3559 FirstShift = Mips::DSLL;
3560 SecondShift = Mips::DSRL32;
3561 }
3562 if (ImmValue == 32) {
3563 FirstShift = Mips::DSLL32;
3564 SecondShift = Mips::DSRL32;
3565 }
3566 if ((ImmValue >= 33) && (ImmValue <= 63)) {
3567 FirstShift = Mips::DSLL32;
3568 SecondShift = Mips::DSRL;
3569 }
3570 break;
3571 case Mips::DRORImm:
3572 if ((ImmValue >= 1) && (ImmValue <= 31)) {
3573 FirstShift = Mips::DSRL;
3574 SecondShift = Mips::DSLL32;
3575 }
3576 if (ImmValue == 32) {
3577 FirstShift = Mips::DSRL32;
3578 SecondShift = Mips::DSLL32;
3579 }
3580 if ((ImmValue >= 33) && (ImmValue <= 63)) {
3581 FirstShift = Mips::DSRL32;
3582 SecondShift = Mips::DSLL;
3583 }
3584 break;
3585 }
3586
3587 ATReg = getATReg(Inst.getLoc());
3588 if (!ATReg)
3589 return true;
3590
3591 emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), Instructions);
3592 emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32, Inst.getLoc(), Instructions);
3593 emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions);
3594
3595 return false;
3596 }
3597
3598 return true;
3599}
3600
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003601bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc,
3602 SmallVectorImpl<MCInst> &Instructions) {
3603
3604 unsigned FirstRegOp = Inst.getOperand(0).getReg();
3605 unsigned SecondRegOp = Inst.getOperand(1).getReg();
3606
3607 emitRI(Mips::BGEZ, SecondRegOp, 8, IDLoc, Instructions);
3608 if (FirstRegOp != SecondRegOp)
3609 emitRRR(Mips::ADDu, FirstRegOp, SecondRegOp, Mips::ZERO, IDLoc, Instructions);
3610 else
3611 createNop(false, IDLoc, Instructions);
3612 emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, Instructions);
3613
3614 return false;
3615}
3616
Toma Tabacu234482a2015-03-16 12:03:39 +00003617void MipsAsmParser::createNop(bool hasShortDelaySlot, SMLoc IDLoc,
3618 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003619 if (hasShortDelaySlot)
3620 emitRR(Mips::MOVE16_MM, Mips::ZERO, Mips::ZERO, IDLoc, Instructions);
3621 else
3622 emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, Instructions);
Toma Tabacu234482a2015-03-16 12:03:39 +00003623}
3624
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003625void MipsAsmParser::createAddu(unsigned DstReg, unsigned SrcReg,
Toma Tabacu0b3e9782015-06-23 14:00:54 +00003626 unsigned TrgReg, bool Is64Bit,
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003627 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanders03f9c012015-07-14 12:24:22 +00003628 emitRRR(Is64Bit ? Mips::DADDu : Mips::ADDu, DstReg, SrcReg, TrgReg, SMLoc(),
3629 Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003630}
3631
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003632void MipsAsmParser::createCpRestoreMemOp(
3633 bool IsLoad, int StackOffset, SMLoc IDLoc,
3634 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003635 // If the offset can not fit into 16 bits, we need to expand.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003636 if (!isInt<16>(StackOffset)) {
3637 MCInst MemInst;
3638 MemInst.setOpcode(IsLoad ? Mips::LW : Mips::SW);
3639 MemInst.addOperand(MCOperand::createReg(Mips::GP));
3640 MemInst.addOperand(MCOperand::createReg(Mips::SP));
3641 MemInst.addOperand(MCOperand::createImm(StackOffset));
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003642 expandMemInst(MemInst, IDLoc, Instructions, IsLoad, true /*HasImmOpnd*/);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003643 return;
3644 }
3645
3646 emitRRI(IsLoad ? Mips::LW : Mips::SW, Mips::GP, Mips::SP, StackOffset, IDLoc,
3647 Instructions);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003648}
3649
Matheus Almeida595fcab2014-06-11 15:05:56 +00003650unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
3651 // As described by the Mips32r2 spec, the registers Rd and Rs for
3652 // jalr.hb must be different.
3653 unsigned Opcode = Inst.getOpcode();
3654
3655 if (Opcode == Mips::JALR_HB &&
3656 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
3657 return Match_RequiresDifferentSrcAndDst;
3658
3659 return Match_Success;
3660}
3661
Daniel Sanders52da7af2015-11-06 12:11:03 +00003662static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
3663 uint64_t ErrorInfo) {
3664 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
3665 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
3666 if (ErrorLoc == SMLoc())
3667 return Loc;
3668 return ErrorLoc;
3669 }
3670 return Loc;
3671}
3672
David Blaikie960ea3f2014-06-08 16:18:35 +00003673bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3674 OperandVector &Operands,
3675 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003676 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00003677 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00003678
Jack Carterb4dbc172012-09-05 23:34:03 +00003679 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00003680 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00003681 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003682 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00003683
3684 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003685 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003686 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00003687 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00003688 for (unsigned i = 0; i < Instructions.size(); i++)
Akira Hatanakabd9fc282015-11-14 05:20:05 +00003689 Out.EmitInstruction(Instructions[i], getSTI());
Jack Carterb4dbc172012-09-05 23:34:03 +00003690 return false;
3691 }
3692 case Match_MissingFeature:
3693 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
3694 return true;
3695 case Match_InvalidOperand: {
3696 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00003697 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003698 if (ErrorInfo >= Operands.size())
3699 return Error(IDLoc, "too few operands for instruction");
3700
Daniel Sanders52da7af2015-11-06 12:11:03 +00003701 ErrorLoc = Operands[ErrorInfo]->getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00003702 if (ErrorLoc == SMLoc())
3703 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00003704 }
3705
3706 return Error(ErrorLoc, "invalid operand for instruction");
3707 }
3708 case Match_MnemonicFail:
3709 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00003710 case Match_RequiresDifferentSrcAndDst:
3711 return Error(IDLoc, "source and destination must be different");
Daniel Sanders52da7af2015-11-06 12:11:03 +00003712 case Match_Immz:
3713 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00003714 case Match_UImm1_0:
3715 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3716 "expected 1-bit unsigned immediate");
Daniel Sandersea4f6532015-11-06 12:22:31 +00003717 case Match_UImm2_0:
3718 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3719 "expected 2-bit unsigned immediate");
3720 case Match_UImm2_1:
3721 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3722 "expected immediate in range 1 .. 4");
Daniel Sanders38ce0f62015-11-06 12:31:27 +00003723 case Match_UImm3_0:
3724 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3725 "expected 3-bit unsigned immediate");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00003726 case Match_UImm4_0:
3727 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3728 "expected 4-bit unsigned immediate");
Daniel Sanders78e89022016-03-11 11:37:50 +00003729 case Match_SImm4_0:
3730 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3731 "expected 4-bit signed immediate");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00003732 case Match_UImm5_0:
3733 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3734 "expected 5-bit unsigned immediate");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00003735 case Match_UImm5_1:
3736 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3737 "expected immediate in range 1 .. 32");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00003738 case Match_UImm5_32:
3739 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3740 "expected immediate in range 32 .. 63");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00003741 case Match_UImm5_33:
3742 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3743 "expected immediate in range 33 .. 64");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00003744 case Match_UImm5_0_Report_UImm6:
3745 // This is used on UImm5 operands that have a corresponding UImm5_32
3746 // operand to avoid confusing the user.
3747 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3748 "expected 6-bit unsigned immediate");
3749 case Match_UImm5_Lsl2:
3750 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3751 "expected both 7-bit unsigned immediate and multiple of 4");
Hrvoje Varga46458d02016-02-25 12:53:29 +00003752 case Match_UImmRange2_64:
3753 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3754 "expected immediate in range 2 .. 64");
Daniel Sanders59d092f2015-12-08 13:49:19 +00003755 case Match_UImm6_0:
3756 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3757 "expected 6-bit unsigned immediate");
Daniel Sanders19b7f762016-03-14 11:16:56 +00003758 case Match_UImm6_Lsl2:
3759 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3760 "expected both 8-bit unsigned immediate and multiple of 4");
Daniel Sanders78e89022016-03-11 11:37:50 +00003761 case Match_SImm6_0:
Zlatko Buljan252cca52015-12-18 08:59:37 +00003762 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3763 "expected 6-bit signed immediate");
3764 case Match_UImm7_0:
3765 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3766 "expected 7-bit unsigned immediate");
Daniel Sanders106d2d42015-12-08 14:42:10 +00003767 case Match_UImm8_0:
3768 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3769 "expected 8-bit unsigned immediate");
Daniel Sanders3c722312015-12-09 13:48:05 +00003770 case Match_UImm10_0:
3771 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3772 "expected 10-bit unsigned immediate");
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00003773 case Match_UImm16:
3774 case Match_UImm16_Relaxed:
3775 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3776 "expected 16-bit unsigned immediate");
Daniel Sanders03a8d2f2016-02-29 16:06:38 +00003777 case Match_UImm20_0:
3778 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3779 "expected 20-bit unsigned immediate");
Jack Carterb4dbc172012-09-05 23:34:03 +00003780 }
Craig Topper589ceee2015-01-03 08:16:34 +00003781
3782 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00003783}
3784
Toma Tabacud9d344b2015-04-27 14:05:04 +00003785void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
3786 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
3787 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
3788 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003789}
3790
Toma Tabacu81496c12015-05-20 08:54:45 +00003791void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
3792 if (!AssemblerOptions.back()->isMacro())
3793 Warning(Loc, "macro instruction expanded into multiple instructions");
3794}
3795
Daniel Sandersef638fe2014-10-03 15:37:37 +00003796void
3797MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
3798 SMRange Range, bool ShowColors) {
3799 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00003800 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00003801 ShowColors);
3802}
3803
Jack Carter1ac53222013-02-20 23:11:17 +00003804int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003805 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003806
Vladimir Medic4c299852013-11-06 11:27:05 +00003807 CC = StringSwitch<unsigned>(Name)
3808 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003809 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00003810 .Case("a0", 4)
3811 .Case("a1", 5)
3812 .Case("a2", 6)
3813 .Case("a3", 7)
3814 .Case("v0", 2)
3815 .Case("v1", 3)
3816 .Case("s0", 16)
3817 .Case("s1", 17)
3818 .Case("s2", 18)
3819 .Case("s3", 19)
3820 .Case("s4", 20)
3821 .Case("s5", 21)
3822 .Case("s6", 22)
3823 .Case("s7", 23)
3824 .Case("k0", 26)
3825 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003826 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00003827 .Case("sp", 29)
3828 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003829 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00003830 .Case("ra", 31)
3831 .Case("t0", 8)
3832 .Case("t1", 9)
3833 .Case("t2", 10)
3834 .Case("t3", 11)
3835 .Case("t4", 12)
3836 .Case("t5", 13)
3837 .Case("t6", 14)
3838 .Case("t7", 15)
3839 .Case("t8", 24)
3840 .Case("t9", 25)
3841 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003842
Toma Tabacufda445c2014-09-15 15:33:01 +00003843 if (!(isABI_N32() || isABI_N64()))
3844 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003845
Daniel Sandersef638fe2014-10-03 15:37:37 +00003846 if (12 <= CC && CC <= 15) {
3847 // Name is one of t4-t7
3848 AsmToken RegTok = getLexer().peekTok();
3849 SMRange RegRange = RegTok.getLocRange();
3850
3851 StringRef FixedName = StringSwitch<StringRef>(Name)
3852 .Case("t4", "t0")
3853 .Case("t5", "t1")
3854 .Case("t6", "t2")
3855 .Case("t7", "t3")
3856 .Default("");
3857 assert(FixedName != "" && "Register name is not one of t4-t7.");
3858
3859 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
3860 "Did you mean $" + FixedName + "?", RegRange);
3861 }
3862
Toma Tabacufda445c2014-09-15 15:33:01 +00003863 // Although SGI documentation just cuts out t0-t3 for n32/n64,
3864 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
3865 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
3866 if (8 <= CC && CC <= 11)
3867 CC += 4;
3868
3869 if (CC == -1)
3870 CC = StringSwitch<unsigned>(Name)
3871 .Case("a4", 8)
3872 .Case("a5", 9)
3873 .Case("a6", 10)
3874 .Case("a7", 11)
3875 .Case("kt0", 26)
3876 .Case("kt1", 27)
3877 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003878
3879 return CC;
3880}
Jack Carterd0bd6422013-04-18 00:41:53 +00003881
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003882int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
3883 int CC;
3884
3885 CC = StringSwitch<unsigned>(Name)
3886 .Case("hwr_cpunum", 0)
3887 .Case("hwr_synci_step", 1)
3888 .Case("hwr_cc", 2)
3889 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00003890 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003891 .Default(-1);
3892
3893 return CC;
3894}
3895
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003896int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003897
Jack Cartera63b16a2012-09-07 00:23:42 +00003898 if (Name[0] == 'f') {
3899 StringRef NumString = Name.substr(1);
3900 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003901 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003902 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003903 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00003904 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003905 return IntVal;
3906 }
3907 return -1;
3908}
Jack Cartera63b16a2012-09-07 00:23:42 +00003909
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003910int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
3911
3912 if (Name.startswith("fcc")) {
3913 StringRef NumString = Name.substr(3);
3914 unsigned IntVal;
3915 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003916 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003917 if (IntVal > 7) // There are only 8 fcc registers.
3918 return -1;
3919 return IntVal;
3920 }
3921 return -1;
3922}
3923
3924int MipsAsmParser::matchACRegisterName(StringRef Name) {
3925
Akira Hatanaka274d24c2013-08-14 01:15:52 +00003926 if (Name.startswith("ac")) {
3927 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003928 unsigned IntVal;
3929 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003930 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003931 if (IntVal > 3) // There are only 3 acc registers.
3932 return -1;
3933 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00003934 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003935 return -1;
3936}
Jack Carterd0bd6422013-04-18 00:41:53 +00003937
Jack Carter5dc8ac92013-09-25 23:50:44 +00003938int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
3939 unsigned IntVal;
3940
3941 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
3942 return -1;
3943
3944 if (IntVal > 31)
3945 return -1;
3946
3947 return IntVal;
3948}
3949
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003950int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
3951 int CC;
3952
3953 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00003954 .Case("msair", 0)
3955 .Case("msacsr", 1)
3956 .Case("msaaccess", 2)
3957 .Case("msasave", 3)
3958 .Case("msamodify", 4)
3959 .Case("msarequest", 5)
3960 .Case("msamap", 6)
3961 .Case("msaunmap", 7)
3962 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003963
3964 return CC;
3965}
3966
Toma Tabacu89a712b2015-04-15 10:48:56 +00003967unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00003968 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00003969 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00003970 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00003971 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00003972 return 0;
3973 }
3974 unsigned AT = getReg(
3975 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00003976 return AT;
3977}
Jack Carter0b744b32012-10-04 02:29:46 +00003978
Jack Carterd0bd6422013-04-18 00:41:53 +00003979unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00003980 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00003981}
3982
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003983unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003984 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00003985 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003986}
3987
Jack Carter873c7242013-01-12 01:03:14 +00003988int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003989 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00003990 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00003991 return -1;
3992
Jack Carter873c7242013-01-12 01:03:14 +00003993 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00003994}
3995
Toma Tabacu13964452014-09-04 13:23:44 +00003996bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003997 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00003998 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003999
Jack Carter30a59822012-10-04 04:03:53 +00004000 // Check if the current operand has a custom associated parser, if so, try to
4001 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00004002 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4003 if (ResTy == MatchOperand_Success)
4004 return false;
4005 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4006 // there was a match, but an error occurred, in which case, just return that
4007 // the operand parsing failed.
4008 if (ResTy == MatchOperand_ParseFail)
4009 return true;
4010
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004011 DEBUG(dbgs() << ".. Generic Parser\n");
4012
Jack Carterb4dbc172012-09-05 23:34:03 +00004013 switch (getLexer().getKind()) {
4014 default:
4015 Error(Parser.getTok().getLoc(), "unexpected token in operand");
4016 return true;
4017 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00004018 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00004019 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00004020
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004021 // Almost all registers have been parsed by custom parsers. There is only
4022 // one exception to this. $zero (and it's alias $0) will reach this point
4023 // for div, divu, and similar instructions because it is not an operand
4024 // to the instruction definition but an explicit register. Special case
4025 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00004026 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00004027 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004028
Jack Carterd0bd6422013-04-18 00:41:53 +00004029 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00004030 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004031 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00004032 return true;
4033
Jack Carter873c7242013-01-12 01:03:14 +00004034 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00004035 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00004036 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00004037 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004038 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00004039
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004040 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004041 return false;
4042 }
Vladimir Medic4c299852013-11-06 11:27:05 +00004043 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00004044 case AsmToken::LParen:
4045 case AsmToken::Minus:
4046 case AsmToken::Plus:
4047 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00004048 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00004049 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004050 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00004051 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004052 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00004053 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00004054 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00004055 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004056 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00004057 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00004058 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00004059 return true;
4060
Jack Carter873c7242013-01-12 01:03:14 +00004061 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4062
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004063 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00004064 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004065 } // case AsmToken::Percent
4066 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00004067 return true;
4068}
4069
Vladimir Medic4c299852013-11-06 11:27:05 +00004070const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00004071 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00004072 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00004073 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00004074 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00004075 // It's a constant, evaluate reloc value.
4076 int16_t Val;
4077 switch (getVariantKind(RelocStr)) {
4078 case MCSymbolRefExpr::VK_Mips_ABS_LO:
4079 // Get the 1st 16-bits.
4080 Val = MCE->getValue() & 0xffff;
4081 break;
4082 case MCSymbolRefExpr::VK_Mips_ABS_HI:
Simon Atanasyan2fc1e3b2016-02-09 22:31:49 +00004083 case MCSymbolRefExpr::VK_Mips_GOT:
Sasa Stankovic06c47802014-04-03 10:37:45 +00004084 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
4085 // 16 bits being negative.
4086 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
4087 break;
4088 case MCSymbolRefExpr::VK_Mips_HIGHER:
4089 // Get the 3rd 16-bits.
4090 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
4091 break;
4092 case MCSymbolRefExpr::VK_Mips_HIGHEST:
4093 // Get the 4th 16-bits.
4094 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
4095 break;
4096 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00004097 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00004098 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00004099 return MCConstantExpr::create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00004100 }
4101
Jack Carterb5cf5902013-04-17 00:18:04 +00004102 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004103 // It's a symbol, create a symbolic expression from the symbol.
Toma Tabacu07c97b32015-06-17 10:43:45 +00004104 const MCSymbol *Symbol = &MSRE->getSymbol();
Jack Carterb5cf5902013-04-17 00:18:04 +00004105 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004106 Res = MCSymbolRefExpr::create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004107 return Res;
4108 }
4109
4110 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00004111 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
4112
Sasa Stankovic06c47802014-04-03 10:37:45 +00004113 // Try to create target expression.
4114 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
Jim Grosbach13760bd2015-05-30 01:25:56 +00004115 return MipsMCExpr::create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00004116
Jack Carterd0bd6422013-04-18 00:41:53 +00004117 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
4118 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004119 Res = MCBinaryExpr::create(BE->getOpcode(), LExp, RExp, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004120 return Res;
4121 }
4122
4123 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004124 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004125 Res = MCUnaryExpr::create(UN->getOpcode(), UnExp, getContext());
Jack Carterd0bd6422013-04-18 00:41:53 +00004126 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00004127 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004128 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00004129 return Expr;
4130}
4131
4132bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
4133
4134 switch (Expr->getKind()) {
4135 case MCExpr::Constant:
4136 return true;
4137 case MCExpr::SymbolRef:
4138 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
4139 case MCExpr::Binary:
4140 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
4141 if (!isEvaluated(BE->getLHS()))
4142 return false;
4143 return isEvaluated(BE->getRHS());
4144 }
4145 case MCExpr::Unary:
4146 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00004147 case MCExpr::Target:
4148 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004149 }
Jack Carterb5cf5902013-04-17 00:18:04 +00004150 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00004151}
Jack Carterd0bd6422013-04-18 00:41:53 +00004152
Jack Carterb5cf5902013-04-17 00:18:04 +00004153bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004154 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00004155 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00004156 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00004157 if (Tok.isNot(AsmToken::Identifier))
4158 return true;
4159
Yaron Keren075759a2015-03-30 15:42:36 +00004160 std::string Str = Tok.getIdentifier();
Jack Carterb5cf5902013-04-17 00:18:04 +00004161
Jack Carterd0bd6422013-04-18 00:41:53 +00004162 Parser.Lex(); // Eat the identifier.
4163 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004164 const MCExpr *IdVal;
4165 SMLoc EndLoc;
4166
4167 if (getLexer().getKind() == AsmToken::LParen) {
4168 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004169 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004170 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004171 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004172 const AsmToken &nextTok = Parser.getTok();
4173 if (nextTok.isNot(AsmToken::Identifier))
4174 return true;
4175 Str += "(%";
4176 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00004177 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00004178 if (getLexer().getKind() != AsmToken::LParen)
4179 return true;
4180 } else
4181 break;
4182 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004183 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00004184 return true;
4185
4186 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00004187 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004188
4189 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00004190 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004191
Jack Carterd0bd6422013-04-18 00:41:53 +00004192 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00004193 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004194}
4195
Jack Carterb4dbc172012-09-05 23:34:03 +00004196bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
4197 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004198 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00004199 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004200 if (ResTy == MatchOperand_Success) {
4201 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00004202 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004203 StartLoc = Operand.getStartLoc();
4204 EndLoc = Operand.getEndLoc();
4205
4206 // AFAIK, we only support numeric registers and named GPR's in CFI
4207 // directives.
4208 // Don't worry about eating tokens before failing. Using an unrecognised
4209 // register is a parse error.
4210 if (Operand.isGPRAsmReg()) {
4211 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004212 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004213 }
4214
4215 return (RegNo == (unsigned)-1);
4216 }
4217
4218 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00004219 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00004220}
4221
Jack Carterb5cf5902013-04-17 00:18:04 +00004222bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004223 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00004224 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00004225 bool Result = true;
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004226 unsigned NumOfLParen = 0;
Jack Carterb5cf5902013-04-17 00:18:04 +00004227
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004228 while (getLexer().getKind() == AsmToken::LParen) {
Jack Carterb5cf5902013-04-17 00:18:04 +00004229 Parser.Lex();
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004230 ++NumOfLParen;
4231 }
Jack Carter873c7242013-01-12 01:03:14 +00004232
Jack Carterd0bd6422013-04-18 00:41:53 +00004233 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00004234 default:
4235 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00004236 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00004237 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00004238 case AsmToken::Integer:
4239 case AsmToken::Minus:
4240 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00004241 if (isParenExpr)
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004242 Result = getParser().parseParenExprOfDepth(NumOfLParen, Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00004243 else
4244 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00004245 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00004246 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004247 break;
Jack Carter873c7242013-01-12 01:03:14 +00004248 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00004249 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00004250 }
Jack Carterb5cf5902013-04-17 00:18:04 +00004251 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004252}
4253
David Blaikie960ea3f2014-06-08 16:18:35 +00004254MipsAsmParser::OperandMatchResultTy
4255MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004256 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004257 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00004258 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00004259 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00004260 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004261 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00004262 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00004263 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00004264
Jack Carterb5cf5902013-04-17 00:18:04 +00004265 if (getLexer().getKind() == AsmToken::LParen) {
4266 Parser.Lex();
4267 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004268 }
4269
Jack Carterb5cf5902013-04-17 00:18:04 +00004270 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004271 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00004272 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004273
Jack Carterd0bd6422013-04-18 00:41:53 +00004274 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004275 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004276 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00004277 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00004278 SMLoc E =
4279 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004280 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00004281 return MatchOperand_Success;
4282 }
4283 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004284 SMLoc E =
4285 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00004286
Jack Carterd0bd6422013-04-18 00:41:53 +00004287 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004288 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00004289 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004290 S, E, *this);
4291 Operands.push_back(
4292 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00004293 return MatchOperand_Success;
4294 }
4295 Error(Parser.getTok().getLoc(), "'(' expected");
4296 return MatchOperand_ParseFail;
4297 }
4298
Jack Carterd0bd6422013-04-18 00:41:53 +00004299 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004300 }
4301
Toma Tabacu13964452014-09-04 13:23:44 +00004302 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004303 if (Res != MatchOperand_Success)
4304 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004305
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004306 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00004307 Error(Parser.getTok().getLoc(), "')' expected");
4308 return MatchOperand_ParseFail;
4309 }
4310
Jack Carter873c7242013-01-12 01:03:14 +00004311 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4312
Jack Carterd0bd6422013-04-18 00:41:53 +00004313 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004314
Craig Topper062a2ba2014-04-25 05:30:21 +00004315 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004316 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00004317
Jack Carterd0bd6422013-04-18 00:41:53 +00004318 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00004319 std::unique_ptr<MipsOperand> op(
4320 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00004321 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004322 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004323 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00004324 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004325 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
4326 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004327 if (IdVal->evaluateAsAbsolute(Imm))
4328 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004329 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004330 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00004331 getContext());
4332 }
4333
David Blaikie960ea3f2014-06-08 16:18:35 +00004334 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004335 return MatchOperand_Success;
4336}
4337
David Blaikie960ea3f2014-06-08 16:18:35 +00004338bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004339 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00004340 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00004341 if (Sym) {
4342 SMLoc S = Parser.getTok().getLoc();
4343 const MCExpr *Expr;
4344 if (Sym->isVariable())
4345 Expr = Sym->getVariableValue();
4346 else
4347 return false;
4348 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004349 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00004350 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00004351 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004352 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004353 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00004354 if (ResTy == MatchOperand_Success) {
4355 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00004356 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00004357 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004358 llvm_unreachable("Should never ParseFail");
4359 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00004360 }
4361 } else if (Expr->getKind() == MCExpr::Constant) {
4362 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00004363 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00004364 Operands.push_back(
4365 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00004366 return true;
4367 }
4368 }
4369 return false;
4370}
Jack Carterd0bd6422013-04-18 00:41:53 +00004371
Jack Carter873c7242013-01-12 01:03:14 +00004372MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004373MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00004374 StringRef Identifier,
4375 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004376 int Index = matchCPURegisterName(Identifier);
4377 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004378 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004379 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4380 return MatchOperand_Success;
4381 }
4382
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004383 Index = matchHWRegsRegisterName(Identifier);
4384 if (Index != -1) {
4385 Operands.push_back(MipsOperand::createHWRegsReg(
4386 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4387 return MatchOperand_Success;
4388 }
4389
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004390 Index = matchFPURegisterName(Identifier);
4391 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004392 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004393 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4394 return MatchOperand_Success;
4395 }
4396
4397 Index = matchFCCRegisterName(Identifier);
4398 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004399 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004400 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4401 return MatchOperand_Success;
4402 }
4403
4404 Index = matchACRegisterName(Identifier);
4405 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004406 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004407 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4408 return MatchOperand_Success;
4409 }
4410
4411 Index = matchMSA128RegisterName(Identifier);
4412 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004413 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004414 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4415 return MatchOperand_Success;
4416 }
4417
4418 Index = matchMSA128CtrlRegisterName(Identifier);
4419 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004420 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004421 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4422 return MatchOperand_Success;
4423 }
4424
4425 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00004426}
4427
4428MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004429MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004430 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00004431 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004432
4433 if (Token.is(AsmToken::Identifier)) {
4434 DEBUG(dbgs() << ".. identifier\n");
4435 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00004436 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004437 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00004438 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004439 } else if (Token.is(AsmToken::Integer)) {
4440 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00004441 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004442 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
4443 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004444 return MatchOperand_Success;
4445 }
4446
4447 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
4448
4449 return MatchOperand_NoMatch;
4450}
4451
David Blaikie960ea3f2014-06-08 16:18:35 +00004452MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004453MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004454 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004455 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004456
4457 auto Token = Parser.getTok();
4458
4459 SMLoc S = Token.getLoc();
4460
4461 if (Token.isNot(AsmToken::Dollar)) {
4462 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
4463 if (Token.is(AsmToken::Identifier)) {
4464 if (searchSymbolAlias(Operands))
4465 return MatchOperand_Success;
4466 }
4467 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
4468 return MatchOperand_NoMatch;
4469 }
4470 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004471
Toma Tabacu13964452014-09-04 13:23:44 +00004472 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00004473 if (ResTy == MatchOperand_Success) {
4474 Parser.Lex(); // $
4475 Parser.Lex(); // identifier
4476 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004477 return ResTy;
4478}
4479
4480MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004481MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004482 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004483 switch (getLexer().getKind()) {
4484 default:
4485 return MatchOperand_NoMatch;
4486 case AsmToken::LParen:
4487 case AsmToken::Minus:
4488 case AsmToken::Plus:
4489 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00004490 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004491 case AsmToken::String:
4492 break;
4493 }
4494
4495 const MCExpr *IdVal;
4496 SMLoc S = Parser.getTok().getLoc();
4497 if (getParser().parseExpression(IdVal))
4498 return MatchOperand_ParseFail;
4499
4500 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4501 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
4502 return MatchOperand_Success;
4503}
4504
David Blaikie960ea3f2014-06-08 16:18:35 +00004505MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004506MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004507 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004508 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004509
4510 SMLoc S = getLexer().getLoc();
4511
4512 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00004513 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004514 if (ResTy != MatchOperand_NoMatch)
4515 return ResTy;
4516
Daniel Sanders315386c2014-04-01 10:40:14 +00004517 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00004518 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00004519 if (ResTy != MatchOperand_NoMatch)
4520 return ResTy;
4521
Daniel Sandersffd84362014-04-01 10:41:48 +00004522 const MCExpr *Expr = nullptr;
4523 if (Parser.parseExpression(Expr)) {
4524 // We have no way of knowing if a symbol was consumed so we must ParseFail
4525 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004526 }
Daniel Sandersffd84362014-04-01 10:41:48 +00004527 Operands.push_back(
4528 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004529 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00004530}
4531
Vladimir Medic2b953d02013-10-01 09:48:56 +00004532MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00004533MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004534 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00004535 const MCExpr *IdVal;
4536 // If the first token is '$' we may have register operand.
4537 if (Parser.getTok().is(AsmToken::Dollar))
4538 return MatchOperand_NoMatch;
4539 SMLoc S = Parser.getTok().getLoc();
4540 if (getParser().parseExpression(IdVal))
4541 return MatchOperand_ParseFail;
4542 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00004543 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00004544 int64_t Val = MCE->getValue();
4545 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4546 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00004547 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00004548 return MatchOperand_Success;
4549}
4550
Matheus Almeida779c5932013-11-18 12:32:49 +00004551MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004552MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004553 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00004554 switch (getLexer().getKind()) {
4555 default:
4556 return MatchOperand_NoMatch;
4557 case AsmToken::LParen:
4558 case AsmToken::Plus:
4559 case AsmToken::Minus:
4560 case AsmToken::Integer:
4561 break;
4562 }
4563
4564 const MCExpr *Expr;
4565 SMLoc S = Parser.getTok().getLoc();
4566
4567 if (getParser().parseExpression(Expr))
4568 return MatchOperand_ParseFail;
4569
4570 int64_t Val;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004571 if (!Expr->evaluateAsAbsolute(Val)) {
Matheus Almeida779c5932013-11-18 12:32:49 +00004572 Error(S, "expected immediate value");
4573 return MatchOperand_ParseFail;
4574 }
4575
4576 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
4577 // and because the CPU always adds one to the immediate field, the allowed
4578 // range becomes 1..4. We'll only check the range here and will deal
4579 // with the addition/subtraction when actually decoding/encoding
4580 // the instruction.
4581 if (Val < 1 || Val > 4) {
4582 Error(S, "immediate not in range (1..4)");
4583 return MatchOperand_ParseFail;
4584 }
4585
Jack Carter3b2c96e2014-01-22 23:31:38 +00004586 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004587 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00004588 return MatchOperand_Success;
4589}
4590
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004591MipsAsmParser::OperandMatchResultTy
4592MipsAsmParser::parseRegisterList(OperandVector &Operands) {
4593 MCAsmParser &Parser = getParser();
4594 SmallVector<unsigned, 10> Regs;
4595 unsigned RegNo;
4596 unsigned PrevReg = Mips::NoRegister;
4597 bool RegRange = false;
4598 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4599
4600 if (Parser.getTok().isNot(AsmToken::Dollar))
4601 return MatchOperand_ParseFail;
4602
4603 SMLoc S = Parser.getTok().getLoc();
4604 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
4605 SMLoc E = getLexer().getLoc();
4606 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
4607 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
4608 if (RegRange) {
4609 // Remove last register operand because registers from register range
4610 // should be inserted first.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004611 if ((isGP64bit() && RegNo == Mips::RA_64) ||
4612 (!isGP64bit() && RegNo == Mips::RA)) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004613 Regs.push_back(RegNo);
4614 } else {
4615 unsigned TmpReg = PrevReg + 1;
4616 while (TmpReg <= RegNo) {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004617 if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) ||
4618 (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) &&
4619 isGP64bit())) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004620 Error(E, "invalid register operand");
4621 return MatchOperand_ParseFail;
4622 }
4623
4624 PrevReg = TmpReg;
4625 Regs.push_back(TmpReg++);
4626 }
4627 }
4628
4629 RegRange = false;
4630 } else {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004631 if ((PrevReg == Mips::NoRegister) &&
4632 ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) ||
4633 (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA)))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004634 Error(E, "$16 or $31 expected");
4635 return MatchOperand_ParseFail;
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004636 } else if (!(((RegNo == Mips::FP || RegNo == Mips::RA ||
4637 (RegNo >= Mips::S0 && RegNo <= Mips::S7)) &&
4638 !isGP64bit()) ||
4639 ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 ||
4640 (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) &&
4641 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004642 Error(E, "invalid register operand");
4643 return MatchOperand_ParseFail;
4644 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004645 ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) ||
4646 (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 &&
4647 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004648 Error(E, "consecutive register numbers expected");
4649 return MatchOperand_ParseFail;
4650 }
4651
4652 Regs.push_back(RegNo);
4653 }
4654
4655 if (Parser.getTok().is(AsmToken::Minus))
4656 RegRange = true;
4657
4658 if (!Parser.getTok().isNot(AsmToken::Minus) &&
4659 !Parser.getTok().isNot(AsmToken::Comma)) {
4660 Error(E, "',' or '-' expected");
4661 return MatchOperand_ParseFail;
4662 }
4663
4664 Lex(); // Consume comma or minus
4665 if (Parser.getTok().isNot(AsmToken::Dollar))
4666 break;
4667
4668 PrevReg = RegNo;
4669 }
4670
4671 SMLoc E = Parser.getTok().getLoc();
4672 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4673 parseMemOperand(Operands);
4674 return MatchOperand_Success;
4675}
4676
Zoran Jovanovic2deca342014-12-16 14:59:10 +00004677MipsAsmParser::OperandMatchResultTy
4678MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
4679 MCAsmParser &Parser = getParser();
4680
4681 SMLoc S = Parser.getTok().getLoc();
4682 if (parseAnyRegister(Operands) != MatchOperand_Success)
4683 return MatchOperand_ParseFail;
4684
4685 SMLoc E = Parser.getTok().getLoc();
4686 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
4687 unsigned Reg = Op.getGPR32Reg();
4688 Operands.pop_back();
4689 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
4690 return MatchOperand_Success;
4691}
4692
Zoran Jovanovic41688672015-02-10 16:36:20 +00004693MipsAsmParser::OperandMatchResultTy
4694MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
4695 MCAsmParser &Parser = getParser();
4696 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4697 SmallVector<unsigned, 10> Regs;
4698
4699 if (Parser.getTok().isNot(AsmToken::Dollar))
4700 return MatchOperand_ParseFail;
4701
4702 SMLoc S = Parser.getTok().getLoc();
4703
4704 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4705 return MatchOperand_ParseFail;
4706
4707 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4708 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4709 Regs.push_back(RegNo);
4710
4711 SMLoc E = Parser.getTok().getLoc();
4712 if (Parser.getTok().isNot(AsmToken::Comma)) {
4713 Error(E, "',' expected");
4714 return MatchOperand_ParseFail;
4715 }
4716
4717 // Remove comma.
4718 Parser.Lex();
4719
4720 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4721 return MatchOperand_ParseFail;
4722
4723 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4724 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4725 Regs.push_back(RegNo);
4726
4727 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4728
4729 return MatchOperand_Success;
4730}
4731
Jack Carterdc1e35d2012-09-06 20:00:02 +00004732MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
4733
Vladimir Medic4c299852013-11-06 11:27:05 +00004734 MCSymbolRefExpr::VariantKind VK =
4735 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
4736 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
4737 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
4738 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
4739 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
4740 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
4741 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
4742 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
4743 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
4744 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
4745 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
4746 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
4747 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
4748 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
4749 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
4750 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
4751 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
4752 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00004753 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
4754 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
4755 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
4756 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
4757 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
4758 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00004759 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
4760 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00004761 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00004762
Matheus Almeida2852af82014-04-22 10:15:54 +00004763 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00004764
Jack Carterdc1e35d2012-09-06 20:00:02 +00004765 return VK;
4766}
Jack Cartera63b16a2012-09-07 00:23:42 +00004767
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004768/// Sometimes (i.e. load/stores) the operand may be followed immediately by
4769/// either this.
4770/// ::= '(', register, ')'
4771/// handle it before we iterate so we don't get tripped up by the lack of
4772/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004773bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004774 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004775 if (getLexer().is(AsmToken::LParen)) {
4776 Operands.push_back(
4777 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
4778 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004779 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004780 SMLoc Loc = getLexer().getLoc();
4781 Parser.eatToEndOfStatement();
4782 return Error(Loc, "unexpected token in argument list");
4783 }
4784 if (Parser.getTok().isNot(AsmToken::RParen)) {
4785 SMLoc Loc = getLexer().getLoc();
4786 Parser.eatToEndOfStatement();
4787 return Error(Loc, "unexpected token, expected ')'");
4788 }
4789 Operands.push_back(
4790 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
4791 Parser.Lex();
4792 }
4793 return false;
4794}
4795
4796/// Sometimes (i.e. in MSA) the operand may be followed immediately by
4797/// either one of these.
4798/// ::= '[', register, ']'
4799/// ::= '[', integer, ']'
4800/// handle it before we iterate so we don't get tripped up by the lack of
4801/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004802bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00004803 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004804 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004805 if (getLexer().is(AsmToken::LBrac)) {
4806 Operands.push_back(
4807 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
4808 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004809 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004810 SMLoc Loc = getLexer().getLoc();
4811 Parser.eatToEndOfStatement();
4812 return Error(Loc, "unexpected token in argument list");
4813 }
4814 if (Parser.getTok().isNot(AsmToken::RBrac)) {
4815 SMLoc Loc = getLexer().getLoc();
4816 Parser.eatToEndOfStatement();
4817 return Error(Loc, "unexpected token, expected ']'");
4818 }
4819 Operands.push_back(
4820 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
4821 Parser.Lex();
4822 }
4823 return false;
4824}
4825
David Blaikie960ea3f2014-06-08 16:18:35 +00004826bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
4827 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004828 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004829 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004830
4831 // We have reached first instruction, module directive are now forbidden.
4832 getTargetStreamer().forbidModuleDirective();
4833
Vladimir Medic74593e62013-07-17 15:00:42 +00004834 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00004835 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00004836 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00004837 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00004838 }
Vladimir Medic64828a12013-07-16 10:07:14 +00004839 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004840 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004841
4842 // Read the remaining operands.
4843 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4844 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004845 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004846 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004847 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004848 return Error(Loc, "unexpected token in argument list");
4849 }
Toma Tabacu13964452014-09-04 13:23:44 +00004850 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004851 return true;
4852 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00004853
Jack Carterd0bd6422013-04-18 00:41:53 +00004854 while (getLexer().is(AsmToken::Comma)) {
4855 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00004856 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004857 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004858 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004859 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004860 return Error(Loc, "unexpected token in argument list");
4861 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004862 // Parse bracket and parenthesis suffixes before we iterate
4863 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00004864 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004865 return true;
4866 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00004867 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004868 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00004869 }
4870 }
Jack Carterb4dbc172012-09-05 23:34:03 +00004871 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4872 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004873 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004874 return Error(Loc, "unexpected token in argument list");
4875 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004876 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00004877 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00004878}
4879
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004880bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004881 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004882 SMLoc Loc = getLexer().getLoc();
4883 Parser.eatToEndOfStatement();
4884 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00004885}
4886
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004887bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004888 return Error(Loc, ErrorMsg);
4889}
4890
Jack Carter0b744b32012-10-04 02:29:46 +00004891bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004892 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004893 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00004894
4895 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00004896 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00004897
4898 Parser.Lex(); // Eat "noat".
4899
Jack Carterd0bd6422013-04-18 00:41:53 +00004900 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004901 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004902 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004903 return false;
4904 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004905
4906 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004907 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004908 return false;
4909}
Jack Carterd0bd6422013-04-18 00:41:53 +00004910
Jack Carter0b744b32012-10-04 02:29:46 +00004911bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00004912 // Line can be: ".set at", which sets $at to $1
4913 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00004914 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00004915 Parser.Lex(); // Eat "at".
4916
Jack Carter0b744b32012-10-04 02:29:46 +00004917 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004918 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00004919 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00004920
4921 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004922 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004923 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00004924 }
4925
4926 if (getLexer().isNot(AsmToken::Equal)) {
4927 reportParseError("unexpected token, expected equals sign");
4928 return false;
4929 }
4930 Parser.Lex(); // Eat "=".
4931
4932 if (getLexer().isNot(AsmToken::Dollar)) {
4933 if (getLexer().is(AsmToken::EndOfStatement)) {
4934 reportParseError("no register specified");
4935 return false;
4936 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00004937 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00004938 return false;
4939 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004940 }
4941 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00004942
Toma Tabacu16a74492015-02-13 10:30:57 +00004943 // Find out what "reg" is.
4944 unsigned AtRegNo;
4945 const AsmToken &Reg = Parser.getTok();
4946 if (Reg.is(AsmToken::Identifier)) {
4947 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
4948 } else if (Reg.is(AsmToken::Integer)) {
4949 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00004950 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00004951 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00004952 return false;
4953 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004954
4955 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00004956 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004957 reportParseError("invalid register");
4958 return false;
4959 }
4960 Parser.Lex(); // Eat "reg".
4961
4962 // If this is not the end of the statement, report an error.
4963 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4964 reportParseError("unexpected token, expected end of statement");
4965 return false;
4966 }
4967
4968 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
4969
4970 Parser.Lex(); // Consume the EndOfStatement.
4971 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004972}
4973
4974bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004975 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004976 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004977 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004978 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004979 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004980 return false;
4981 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004982 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00004983 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004984 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004985 return false;
4986}
4987
4988bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004989 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004990 Parser.Lex();
4991 // If this is not the end of the statement, report an error.
4992 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004993 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004994 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00004995 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004996 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00004997 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004998 Parser.Lex(); // Consume the EndOfStatement.
4999 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005000}
5001
5002bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005003 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00005004 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00005005 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005006 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005007 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005008 return false;
5009 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005010 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00005011 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00005012 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005013 return false;
5014}
5015
5016bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005017 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00005018 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00005019 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005020 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005021 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005022 return false;
5023 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005024 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00005025 reportParseError("`noreorder' must be set before `nomacro'");
5026 return false;
5027 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005028 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00005029 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00005030 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005031 return false;
5032}
Jack Carterd76b2372013-03-21 21:44:16 +00005033
Daniel Sanders44934432014-08-07 12:03:36 +00005034bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005035 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00005036 Parser.Lex();
5037
5038 // If this is not the end of the statement, report an error.
5039 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005040 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00005041
5042 setFeatureBits(Mips::FeatureMSA, "msa");
5043 getTargetStreamer().emitDirectiveSetMsa();
5044 return false;
5045}
5046
5047bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005048 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00005049 Parser.Lex();
5050
5051 // If this is not the end of the statement, report an error.
5052 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005053 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00005054
5055 clearFeatureBits(Mips::FeatureMSA, "msa");
5056 getTargetStreamer().emitDirectiveSetNoMsa();
5057 return false;
5058}
5059
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005060bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005061 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005062 Parser.Lex(); // Eat "nodsp".
5063
5064 // If this is not the end of the statement, report an error.
5065 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5066 reportParseError("unexpected token, expected end of statement");
5067 return false;
5068 }
5069
5070 clearFeatureBits(Mips::FeatureDSP, "dsp");
5071 getTargetStreamer().emitDirectiveSetNoDsp();
5072 return false;
5073}
5074
Toma Tabacucc2502d2014-11-04 17:18:07 +00005075bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005076 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005077 Parser.Lex(); // Eat "mips16".
5078
Jack Carter39536722014-01-22 23:08:42 +00005079 // If this is not the end of the statement, report an error.
5080 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005081 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00005082 return false;
5083 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00005084
5085 setFeatureBits(Mips::FeatureMips16, "mips16");
5086 getTargetStreamer().emitDirectiveSetMips16();
5087 Parser.Lex(); // Consume the EndOfStatement.
5088 return false;
5089}
5090
5091bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005092 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005093 Parser.Lex(); // Eat "nomips16".
5094
5095 // If this is not the end of the statement, report an error.
5096 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5097 reportParseError("unexpected token, expected end of statement");
5098 return false;
5099 }
5100
5101 clearFeatureBits(Mips::FeatureMips16, "mips16");
5102 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00005103 Parser.Lex(); // Consume the EndOfStatement.
5104 return false;
5105}
5106
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005107bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005108 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005109 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005110 // Line can be: .set fp=32
5111 // .set fp=xx
5112 // .set fp=64
5113 Parser.Lex(); // Eat fp token
5114 AsmToken Tok = Parser.getTok();
5115 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005116 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005117 return false;
5118 }
5119 Parser.Lex(); // Eat '=' token.
5120 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005121
5122 if (!parseFpABIValue(FpAbiVal, ".set"))
5123 return false;
5124
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005125 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005126 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005127 return false;
5128 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005129 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005130 Parser.Lex(); // Consume the EndOfStatement.
5131 return false;
5132}
5133
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005134bool MipsAsmParser::parseSetOddSPRegDirective() {
5135 MCAsmParser &Parser = getParser();
5136
5137 Parser.Lex(); // Eat "oddspreg".
5138 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5139 reportParseError("unexpected token, expected end of statement");
5140 return false;
5141 }
5142
5143 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5144 getTargetStreamer().emitDirectiveSetOddSPReg();
5145 return false;
5146}
5147
5148bool MipsAsmParser::parseSetNoOddSPRegDirective() {
5149 MCAsmParser &Parser = getParser();
5150
5151 Parser.Lex(); // Eat "nooddspreg".
5152 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5153 reportParseError("unexpected token, expected end of statement");
5154 return false;
5155 }
5156
5157 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5158 getTargetStreamer().emitDirectiveSetNoOddSPReg();
5159 return false;
5160}
5161
Toma Tabacu9db22db2014-09-09 10:15:38 +00005162bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005163 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005164 SMLoc Loc = getLexer().getLoc();
5165
5166 Parser.Lex();
5167 if (getLexer().isNot(AsmToken::EndOfStatement))
5168 return reportParseError("unexpected token, expected end of statement");
5169
5170 // Always keep an element on the options "stack" to prevent the user
5171 // from changing the initial options. This is how we remember them.
5172 if (AssemblerOptions.size() == 2)
5173 return reportParseError(Loc, ".set pop with no .set push");
5174
Akira Hatanakab11ef082015-11-14 06:35:56 +00005175 MCSubtargetInfo &STI = copySTI();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005176 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005177 setAvailableFeatures(
5178 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
5179 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00005180
5181 getTargetStreamer().emitDirectiveSetPop();
5182 return false;
5183}
5184
5185bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005186 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005187 Parser.Lex();
5188 if (getLexer().isNot(AsmToken::EndOfStatement))
5189 return reportParseError("unexpected token, expected end of statement");
5190
5191 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00005192 AssemblerOptions.push_back(
5193 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00005194
5195 getTargetStreamer().emitDirectiveSetPush();
5196 return false;
5197}
5198
Toma Tabacu29696502015-06-02 09:48:04 +00005199bool MipsAsmParser::parseSetSoftFloatDirective() {
5200 MCAsmParser &Parser = getParser();
5201 Parser.Lex();
5202 if (getLexer().isNot(AsmToken::EndOfStatement))
5203 return reportParseError("unexpected token, expected end of statement");
5204
5205 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5206 getTargetStreamer().emitDirectiveSetSoftFloat();
5207 return false;
5208}
5209
5210bool MipsAsmParser::parseSetHardFloatDirective() {
5211 MCAsmParser &Parser = getParser();
5212 Parser.Lex();
5213 if (getLexer().isNot(AsmToken::EndOfStatement))
5214 return reportParseError("unexpected token, expected end of statement");
5215
5216 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5217 getTargetStreamer().emitDirectiveSetHardFloat();
5218 return false;
5219}
5220
Jack Carterd76b2372013-03-21 21:44:16 +00005221bool MipsAsmParser::parseSetAssignment() {
5222 StringRef Name;
5223 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00005224 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00005225
5226 if (Parser.parseIdentifier(Name))
5227 reportParseError("expected identifier after .set");
5228
5229 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005230 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00005231 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00005232
Jack Carter3b2c96e2014-01-22 23:31:38 +00005233 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00005234 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00005235
Jim Grosbach6f482002015-05-18 18:43:14 +00005236 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00005237 Sym->setVariableValue(Value);
5238
5239 return false;
5240}
Jack Carterd0bd6422013-04-18 00:41:53 +00005241
Toma Tabacu26647792014-09-09 12:52:14 +00005242bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005243 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00005244 Parser.Lex();
5245 if (getLexer().isNot(AsmToken::EndOfStatement))
5246 return reportParseError("unexpected token, expected end of statement");
5247
5248 // Reset assembler options to their initial values.
Akira Hatanakab11ef082015-11-14 06:35:56 +00005249 MCSubtargetInfo &STI = copySTI();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005250 setAvailableFeatures(
5251 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
5252 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00005253 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
5254
5255 getTargetStreamer().emitDirectiveSetMips0();
5256 return false;
5257}
5258
Toma Tabacu85618b32014-08-19 14:22:52 +00005259bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005260 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00005261 Parser.Lex();
5262 if (getLexer().isNot(AsmToken::Equal))
5263 return reportParseError("unexpected token, expected equals sign");
5264
5265 Parser.Lex();
5266 StringRef Arch;
5267 if (Parser.parseIdentifier(Arch))
5268 return reportParseError("expected arch identifier");
5269
5270 StringRef ArchFeatureName =
5271 StringSwitch<StringRef>(Arch)
5272 .Case("mips1", "mips1")
5273 .Case("mips2", "mips2")
5274 .Case("mips3", "mips3")
5275 .Case("mips4", "mips4")
5276 .Case("mips5", "mips5")
5277 .Case("mips32", "mips32")
5278 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005279 .Case("mips32r3", "mips32r3")
5280 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005281 .Case("mips32r6", "mips32r6")
5282 .Case("mips64", "mips64")
5283 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005284 .Case("mips64r3", "mips64r3")
5285 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005286 .Case("mips64r6", "mips64r6")
5287 .Case("cnmips", "cnmips")
5288 .Case("r4000", "mips3") // This is an implementation of Mips3.
5289 .Default("");
5290
5291 if (ArchFeatureName.empty())
5292 return reportParseError("unsupported architecture");
5293
5294 selectArch(ArchFeatureName);
5295 getTargetStreamer().emitDirectiveSetArch(Arch);
5296 return false;
5297}
5298
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005299bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005300 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005301 Parser.Lex();
5302 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005303 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005304
Matheus Almeida2852af82014-04-22 10:15:54 +00005305 switch (Feature) {
5306 default:
5307 llvm_unreachable("Unimplemented feature");
5308 case Mips::FeatureDSP:
5309 setFeatureBits(Mips::FeatureDSP, "dsp");
5310 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005311 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005312 case Mips::FeatureMicroMips:
5313 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005314 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005315 case Mips::FeatureMips1:
5316 selectArch("mips1");
5317 getTargetStreamer().emitDirectiveSetMips1();
5318 break;
5319 case Mips::FeatureMips2:
5320 selectArch("mips2");
5321 getTargetStreamer().emitDirectiveSetMips2();
5322 break;
5323 case Mips::FeatureMips3:
5324 selectArch("mips3");
5325 getTargetStreamer().emitDirectiveSetMips3();
5326 break;
5327 case Mips::FeatureMips4:
5328 selectArch("mips4");
5329 getTargetStreamer().emitDirectiveSetMips4();
5330 break;
5331 case Mips::FeatureMips5:
5332 selectArch("mips5");
5333 getTargetStreamer().emitDirectiveSetMips5();
5334 break;
5335 case Mips::FeatureMips32:
5336 selectArch("mips32");
5337 getTargetStreamer().emitDirectiveSetMips32();
5338 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005339 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005340 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005341 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005342 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005343 case Mips::FeatureMips32r3:
5344 selectArch("mips32r3");
5345 getTargetStreamer().emitDirectiveSetMips32R3();
5346 break;
5347 case Mips::FeatureMips32r5:
5348 selectArch("mips32r5");
5349 getTargetStreamer().emitDirectiveSetMips32R5();
5350 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005351 case Mips::FeatureMips32r6:
5352 selectArch("mips32r6");
5353 getTargetStreamer().emitDirectiveSetMips32R6();
5354 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005355 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005356 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00005357 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005358 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005359 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005360 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005361 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005362 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005363 case Mips::FeatureMips64r3:
5364 selectArch("mips64r3");
5365 getTargetStreamer().emitDirectiveSetMips64R3();
5366 break;
5367 case Mips::FeatureMips64r5:
5368 selectArch("mips64r5");
5369 getTargetStreamer().emitDirectiveSetMips64R5();
5370 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005371 case Mips::FeatureMips64r6:
5372 selectArch("mips64r6");
5373 getTargetStreamer().emitDirectiveSetMips64R6();
5374 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005375 }
5376 return false;
5377}
5378
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005379bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005380 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005381 if (getLexer().isNot(AsmToken::Comma)) {
5382 SMLoc Loc = getLexer().getLoc();
5383 Parser.eatToEndOfStatement();
5384 return Error(Loc, ErrorStr);
5385 }
5386
Matheus Almeida2852af82014-04-22 10:15:54 +00005387 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005388 return true;
5389}
5390
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005391// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
5392// In this class, it is only used for .cprestore.
5393// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
5394// MipsTargetELFStreamer and MipsAsmParser.
5395bool MipsAsmParser::isPicAndNotNxxAbi() {
5396 return inPicMode() && !(isABI_N32() || isABI_N64());
5397}
5398
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005399bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00005400 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00005401 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005402
Toma Tabacudde4c462014-11-06 10:02:45 +00005403 if (inMips16Mode()) {
5404 reportParseError(".cpload is not supported in Mips16 mode");
5405 return false;
5406 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005407
David Blaikie960ea3f2014-06-08 16:18:35 +00005408 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00005409 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005410 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5411 reportParseError("expected register containing function address");
5412 return false;
5413 }
5414
David Blaikie960ea3f2014-06-08 16:18:35 +00005415 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
5416 if (!RegOpnd.isGPRAsmReg()) {
5417 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005418 return false;
5419 }
5420
Toma Tabacudde4c462014-11-06 10:02:45 +00005421 // If this is not the end of the statement, report an error.
5422 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5423 reportParseError("unexpected token, expected end of statement");
5424 return false;
5425 }
5426
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005427 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005428 return false;
5429}
5430
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005431bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
5432 MCAsmParser &Parser = getParser();
5433
5434 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
5435 // is used in non-PIC mode.
5436
5437 if (inMips16Mode()) {
5438 reportParseError(".cprestore is not supported in Mips16 mode");
5439 return false;
5440 }
5441
5442 // Get the stack offset value.
5443 const MCExpr *StackOffset;
5444 int64_t StackOffsetVal;
5445 if (Parser.parseExpression(StackOffset)) {
5446 reportParseError("expected stack offset value");
5447 return false;
5448 }
5449
5450 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
5451 reportParseError("stack offset is not an absolute expression");
5452 return false;
5453 }
5454
5455 if (StackOffsetVal < 0) {
5456 Warning(Loc, ".cprestore with negative stack offset has no effect");
5457 IsCpRestoreSet = false;
5458 } else {
5459 IsCpRestoreSet = true;
5460 CpRestoreOffset = StackOffsetVal;
5461 }
5462
5463 // If this is not the end of the statement, report an error.
5464 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5465 reportParseError("unexpected token, expected end of statement");
5466 return false;
5467 }
5468
5469 // Store the $gp on the stack.
5470 SmallVector<MCInst, 3> StoreInsts;
5471 createCpRestoreMemOp(false /*IsLoad*/, CpRestoreOffset /*StackOffset*/, Loc,
5472 StoreInsts);
5473
5474 getTargetStreamer().emitDirectiveCpRestore(StoreInsts, CpRestoreOffset);
5475 Parser.Lex(); // Consume the EndOfStatement.
5476 return false;
5477}
5478
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005479bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005480 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005481 unsigned FuncReg;
5482 unsigned Save;
5483 bool SaveIsReg = true;
5484
Matheus Almeida7e815762014-06-18 13:08:59 +00005485 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005486 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005487 if (ResTy == MatchOperand_NoMatch) {
5488 reportParseError("expected register containing function address");
5489 Parser.eatToEndOfStatement();
5490 return false;
5491 }
5492
5493 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5494 if (!FuncRegOpnd.isGPRAsmReg()) {
5495 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
5496 Parser.eatToEndOfStatement();
5497 return false;
5498 }
5499
5500 FuncReg = FuncRegOpnd.getGPR32Reg();
5501 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005502
Toma Tabacu65f10572014-09-16 15:00:52 +00005503 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005504 return true;
5505
Toma Tabacu13964452014-09-04 13:23:44 +00005506 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005507 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00005508 const MCExpr *OffsetExpr;
5509 int64_t OffsetVal;
5510 SMLoc ExprLoc = getLexer().getLoc();
5511
5512 if (Parser.parseExpression(OffsetExpr) ||
5513 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
5514 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00005515 Parser.eatToEndOfStatement();
5516 return false;
5517 }
Daniel Sanders5d796282015-09-21 09:26:55 +00005518
5519 Save = OffsetVal;
5520 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00005521 } else {
5522 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5523 if (!SaveOpnd.isGPRAsmReg()) {
5524 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
5525 Parser.eatToEndOfStatement();
5526 return false;
5527 }
5528 Save = SaveOpnd.getGPR32Reg();
5529 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005530
Toma Tabacu65f10572014-09-16 15:00:52 +00005531 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005532 return true;
5533
Toma Tabacu8874eac2015-02-18 13:46:53 +00005534 const MCExpr *Expr;
5535 if (Parser.parseExpression(Expr)) {
5536 reportParseError("expected expression");
5537 return false;
5538 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005539
Toma Tabacu8874eac2015-02-18 13:46:53 +00005540 if (Expr->getKind() != MCExpr::SymbolRef) {
5541 reportParseError("expected symbol");
5542 return false;
5543 }
5544 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
5545
Daniel Sandersf173dda2015-09-22 10:50:09 +00005546 CpSaveLocation = Save;
5547 CpSaveLocationIsRegister = SaveIsReg;
5548
Toma Tabacu8874eac2015-02-18 13:46:53 +00005549 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
5550 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005551 return false;
5552}
5553
Daniel Sandersf173dda2015-09-22 10:50:09 +00005554bool MipsAsmParser::parseDirectiveCPReturn() {
5555 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
5556 CpSaveLocationIsRegister);
5557 return false;
5558}
5559
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005560bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005561 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005562 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5563 const AsmToken &Tok = Parser.getTok();
5564
5565 if (Tok.getString() == "2008") {
5566 Parser.Lex();
5567 getTargetStreamer().emitDirectiveNaN2008();
5568 return false;
5569 } else if (Tok.getString() == "legacy") {
5570 Parser.Lex();
5571 getTargetStreamer().emitDirectiveNaNLegacy();
5572 return false;
5573 }
5574 }
5575 // If we don't recognize the option passed to the .nan
5576 // directive (e.g. no option or unknown option), emit an error.
5577 reportParseError("invalid option in .nan directive");
5578 return false;
5579}
5580
Jack Carter0b744b32012-10-04 02:29:46 +00005581bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005582 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005583 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00005584 const AsmToken &Tok = Parser.getTok();
5585
5586 if (Tok.getString() == "noat") {
5587 return parseSetNoAtDirective();
5588 } else if (Tok.getString() == "at") {
5589 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00005590 } else if (Tok.getString() == "arch") {
5591 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005592 } else if (Tok.getString() == "fp") {
5593 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005594 } else if (Tok.getString() == "oddspreg") {
5595 return parseSetOddSPRegDirective();
5596 } else if (Tok.getString() == "nooddspreg") {
5597 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005598 } else if (Tok.getString() == "pop") {
5599 return parseSetPopDirective();
5600 } else if (Tok.getString() == "push") {
5601 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00005602 } else if (Tok.getString() == "reorder") {
5603 return parseSetReorderDirective();
5604 } else if (Tok.getString() == "noreorder") {
5605 return parseSetNoReorderDirective();
5606 } else if (Tok.getString() == "macro") {
5607 return parseSetMacroDirective();
5608 } else if (Tok.getString() == "nomacro") {
5609 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00005610 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00005611 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005612 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00005613 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005614 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00005615 getTargetStreamer().emitDirectiveSetNoMicroMips();
5616 Parser.eatToEndOfStatement();
5617 return false;
5618 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005619 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00005620 } else if (Tok.getString() == "mips0") {
5621 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00005622 } else if (Tok.getString() == "mips1") {
5623 return parseSetFeature(Mips::FeatureMips1);
5624 } else if (Tok.getString() == "mips2") {
5625 return parseSetFeature(Mips::FeatureMips2);
5626 } else if (Tok.getString() == "mips3") {
5627 return parseSetFeature(Mips::FeatureMips3);
5628 } else if (Tok.getString() == "mips4") {
5629 return parseSetFeature(Mips::FeatureMips4);
5630 } else if (Tok.getString() == "mips5") {
5631 return parseSetFeature(Mips::FeatureMips5);
5632 } else if (Tok.getString() == "mips32") {
5633 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00005634 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005635 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005636 } else if (Tok.getString() == "mips32r3") {
5637 return parseSetFeature(Mips::FeatureMips32r3);
5638 } else if (Tok.getString() == "mips32r5") {
5639 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005640 } else if (Tok.getString() == "mips32r6") {
5641 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005642 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005643 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005644 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005645 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005646 } else if (Tok.getString() == "mips64r3") {
5647 return parseSetFeature(Mips::FeatureMips64r3);
5648 } else if (Tok.getString() == "mips64r5") {
5649 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005650 } else if (Tok.getString() == "mips64r6") {
5651 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00005652 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005653 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005654 } else if (Tok.getString() == "nodsp") {
5655 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00005656 } else if (Tok.getString() == "msa") {
5657 return parseSetMsaDirective();
5658 } else if (Tok.getString() == "nomsa") {
5659 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00005660 } else if (Tok.getString() == "softfloat") {
5661 return parseSetSoftFloatDirective();
5662 } else if (Tok.getString() == "hardfloat") {
5663 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00005664 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00005665 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00005666 parseSetAssignment();
5667 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005668 }
Jack Carter07c818d2013-01-25 01:31:34 +00005669
Jack Carter0b744b32012-10-04 02:29:46 +00005670 return true;
5671}
5672
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005673/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00005674/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005675bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005676 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005677 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5678 for (;;) {
5679 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005680 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00005681 return true;
5682
5683 getParser().getStreamer().EmitValue(Value, Size);
5684
5685 if (getLexer().is(AsmToken::EndOfStatement))
5686 break;
5687
Jack Carter07c818d2013-01-25 01:31:34 +00005688 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005689 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00005690 Parser.Lex();
5691 }
5692 }
5693
5694 Parser.Lex();
5695 return false;
5696}
5697
Vladimir Medic4c299852013-11-06 11:27:05 +00005698/// parseDirectiveGpWord
5699/// ::= .gpword local_sym
5700bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005701 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00005702 const MCExpr *Value;
5703 // EmitGPRel32Value requires an expression, so we are using base class
5704 // method to evaluate the expression.
5705 if (getParser().parseExpression(Value))
5706 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00005707 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00005708
Vladimir Medice10c1122013-11-13 13:18:04 +00005709 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005710 return Error(getLexer().getLoc(),
5711 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00005712 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00005713 return false;
5714}
5715
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005716/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00005717/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005718bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005719 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005720 const MCExpr *Value;
5721 // EmitGPRel64Value requires an expression, so we are using base class
5722 // method to evaluate the expression.
5723 if (getParser().parseExpression(Value))
5724 return true;
5725 getParser().getStreamer().EmitGPRel64Value(Value);
5726
5727 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005728 return Error(getLexer().getLoc(),
5729 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00005730 Parser.Lex(); // Eat EndOfStatement token.
5731 return false;
5732}
5733
Jack Carter0cd3c192014-01-06 23:27:31 +00005734bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005735 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00005736 // Get the option token.
5737 AsmToken Tok = Parser.getTok();
5738 // At the moment only identifiers are supported.
5739 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005740 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00005741 Parser.eatToEndOfStatement();
5742 return false;
5743 }
5744
5745 StringRef Option = Tok.getIdentifier();
5746
5747 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005748 // MipsAsmParser needs to know if the current PIC mode changes.
5749 IsPicEnabled = false;
5750
Jack Carter0cd3c192014-01-06 23:27:31 +00005751 getTargetStreamer().emitDirectiveOptionPic0();
5752 Parser.Lex();
5753 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5754 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005755 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005756 Parser.eatToEndOfStatement();
5757 }
5758 return false;
5759 }
5760
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005761 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005762 // MipsAsmParser needs to know if the current PIC mode changes.
5763 IsPicEnabled = true;
5764
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005765 getTargetStreamer().emitDirectiveOptionPic2();
5766 Parser.Lex();
5767 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5768 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005769 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005770 Parser.eatToEndOfStatement();
5771 }
5772 return false;
5773 }
5774
Jack Carter0cd3c192014-01-06 23:27:31 +00005775 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00005776 Warning(Parser.getTok().getLoc(),
5777 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00005778 Parser.eatToEndOfStatement();
5779 return false;
5780}
5781
Toma Tabacu9ca50962015-04-16 09:53:47 +00005782/// parseInsnDirective
5783/// ::= .insn
5784bool MipsAsmParser::parseInsnDirective() {
5785 // If this is not the end of the statement, report an error.
5786 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5787 reportParseError("unexpected token, expected end of statement");
5788 return false;
5789 }
5790
5791 // The actual label marking happens in
5792 // MipsELFStreamer::createPendingLabelRelocs().
5793 getTargetStreamer().emitDirectiveInsn();
5794
5795 getParser().Lex(); // Eat EndOfStatement token.
5796 return false;
5797}
5798
Simon Atanasyanbe186202016-02-11 06:45:54 +00005799/// parseSSectionDirective
5800/// ::= .sbss
5801/// ::= .sdata
5802bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) {
5803 // If this is not the end of the statement, report an error.
5804 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5805 reportParseError("unexpected token, expected end of statement");
5806 return false;
5807 }
5808
5809 MCSection *ELFSection = getContext().getELFSection(
5810 Section, Type, ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL);
5811 getParser().getStreamer().SwitchSection(ELFSection);
5812
5813 getParser().Lex(); // Eat EndOfStatement token.
5814 return false;
5815}
5816
Daniel Sanders7e527422014-07-10 13:38:23 +00005817/// parseDirectiveModule
5818/// ::= .module oddspreg
5819/// ::= .module nooddspreg
5820/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00005821/// ::= .module softfloat
5822/// ::= .module hardfloat
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005823bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005824 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005825 MCAsmLexer &Lexer = getLexer();
5826 SMLoc L = Lexer.getLoc();
5827
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00005828 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005829 // TODO : get a better message.
5830 reportParseError(".module directive must appear before any code");
5831 return false;
5832 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005833
Toma Tabacuc405c822015-01-23 10:40:19 +00005834 StringRef Option;
5835 if (Parser.parseIdentifier(Option)) {
5836 reportParseError("expected .module option identifier");
5837 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005838 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005839
Toma Tabacuc405c822015-01-23 10:40:19 +00005840 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005841 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005842
Toma Tabacu3c499582015-06-25 10:56:57 +00005843 // Synchronize the abiflags information with the FeatureBits information we
5844 // changed above.
5845 getTargetStreamer().updateABIInfo(*this);
5846
5847 // If printing assembly, use the recently updated abiflags information.
5848 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5849 // emitted at the end).
5850 getTargetStreamer().emitDirectiveModuleOddSPReg();
5851
Toma Tabacuc405c822015-01-23 10:40:19 +00005852 // If this is not the end of the statement, report an error.
5853 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5854 reportParseError("unexpected token, expected end of statement");
5855 return false;
5856 }
5857
5858 return false; // parseDirectiveModule has finished successfully.
5859 } else if (Option == "nooddspreg") {
5860 if (!isABI_O32()) {
5861 Error(L, "'.module nooddspreg' requires the O32 ABI");
5862 return false;
5863 }
5864
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005865 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005866
Toma Tabacu3c499582015-06-25 10:56:57 +00005867 // Synchronize the abiflags information with the FeatureBits information we
5868 // changed above.
5869 getTargetStreamer().updateABIInfo(*this);
5870
5871 // If printing assembly, use the recently updated abiflags information.
5872 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5873 // emitted at the end).
5874 getTargetStreamer().emitDirectiveModuleOddSPReg();
5875
Toma Tabacuc405c822015-01-23 10:40:19 +00005876 // If this is not the end of the statement, report an error.
5877 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5878 reportParseError("unexpected token, expected end of statement");
5879 return false;
5880 }
5881
5882 return false; // parseDirectiveModule has finished successfully.
5883 } else if (Option == "fp") {
5884 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00005885 } else if (Option == "softfloat") {
5886 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5887
5888 // Synchronize the ABI Flags information with the FeatureBits information we
5889 // updated above.
5890 getTargetStreamer().updateABIInfo(*this);
5891
5892 // If printing assembly, use the recently updated ABI Flags information.
5893 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5894 // emitted later).
5895 getTargetStreamer().emitDirectiveModuleSoftFloat();
5896
5897 // If this is not the end of the statement, report an error.
5898 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5899 reportParseError("unexpected token, expected end of statement");
5900 return false;
5901 }
5902
5903 return false; // parseDirectiveModule has finished successfully.
5904 } else if (Option == "hardfloat") {
5905 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5906
5907 // Synchronize the ABI Flags information with the FeatureBits information we
5908 // updated above.
5909 getTargetStreamer().updateABIInfo(*this);
5910
5911 // If printing assembly, use the recently updated ABI Flags information.
5912 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5913 // emitted later).
5914 getTargetStreamer().emitDirectiveModuleHardFloat();
5915
5916 // If this is not the end of the statement, report an error.
5917 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5918 reportParseError("unexpected token, expected end of statement");
5919 return false;
5920 }
5921
5922 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00005923 } else {
5924 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
5925 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005926}
5927
5928/// parseDirectiveModuleFP
5929/// ::= =32
5930/// ::= =xx
5931/// ::= =64
5932bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005933 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005934 MCAsmLexer &Lexer = getLexer();
5935
5936 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005937 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005938 return false;
5939 }
5940 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005941
Daniel Sanders7e527422014-07-10 13:38:23 +00005942 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005943 if (!parseFpABIValue(FpABI, ".module"))
5944 return false;
5945
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005946 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005947 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005948 return false;
5949 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005950
Toma Tabacua64e5402015-06-25 12:44:38 +00005951 // Synchronize the abiflags information with the FeatureBits information we
5952 // changed above.
5953 getTargetStreamer().updateABIInfo(*this);
5954
5955 // If printing assembly, use the recently updated abiflags information.
5956 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5957 // emitted at the end).
5958 getTargetStreamer().emitDirectiveModuleFP();
5959
Daniel Sanders7e527422014-07-10 13:38:23 +00005960 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005961 return false;
5962}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005963
Daniel Sanders7e527422014-07-10 13:38:23 +00005964bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005965 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005966 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005967 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005968 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005969
5970 if (Lexer.is(AsmToken::Identifier)) {
5971 StringRef Value = Parser.getTok().getString();
5972 Parser.Lex();
5973
5974 if (Value != "xx") {
5975 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5976 return false;
5977 }
5978
5979 if (!isABI_O32()) {
5980 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
5981 return false;
5982 }
5983
Daniel Sanders7e527422014-07-10 13:38:23 +00005984 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005985 if (ModuleLevelOptions) {
5986 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5987 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5988 } else {
5989 setFeatureBits(Mips::FeatureFPXX, "fpxx");
5990 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5991 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005992 return true;
5993 }
5994
5995 if (Lexer.is(AsmToken::Integer)) {
5996 unsigned Value = Parser.getTok().getIntVal();
5997 Parser.Lex();
5998
5999 if (Value != 32 && Value != 64) {
6000 reportParseError("unsupported value, expected 'xx', '32' or '64'");
6001 return false;
6002 }
6003
6004 if (Value == 32) {
6005 if (!isABI_O32()) {
6006 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
6007 return false;
6008 }
6009
Daniel Sanders7e527422014-07-10 13:38:23 +00006010 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006011 if (ModuleLevelOptions) {
6012 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6013 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6014 } else {
6015 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
6016 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
6017 }
Toma Tabacua64e5402015-06-25 12:44:38 +00006018 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00006019 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006020 if (ModuleLevelOptions) {
6021 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6022 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6023 } else {
6024 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
6025 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
6026 }
Toma Tabacua64e5402015-06-25 12:44:38 +00006027 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006028
Daniel Sanders7e527422014-07-10 13:38:23 +00006029 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006030 }
6031
6032 return false;
6033}
6034
Jack Carter0b744b32012-10-04 02:29:46 +00006035bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006036 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00006037 StringRef IDVal = DirectiveID.getString();
6038
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006039 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00006040 return parseDirectiveCpLoad(DirectiveID.getLoc());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006041 if (IDVal == ".cprestore")
6042 return parseDirectiveCpRestore(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00006043 if (IDVal == ".dword") {
6044 parseDataDirective(8, DirectiveID.getLoc());
6045 return false;
6046 }
Jack Carterd0bd6422013-04-18 00:41:53 +00006047 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006048 StringRef SymbolName;
6049
6050 if (Parser.parseIdentifier(SymbolName)) {
6051 reportParseError("expected identifier after .ent");
6052 return false;
6053 }
6054
6055 // There's an undocumented extension that allows an integer to
6056 // follow the name of the procedure which AFAICS is ignored by GAS.
6057 // Example: .ent foo,2
6058 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6059 if (getLexer().isNot(AsmToken::Comma)) {
6060 // Even though we accept this undocumented extension for compatibility
6061 // reasons, the additional integer argument does not actually change
6062 // the behaviour of the '.ent' directive, so we would like to discourage
6063 // its use. We do this by not referring to the extended version in
6064 // error messages which are not directly related to its use.
6065 reportParseError("unexpected token, expected end of statement");
6066 return false;
6067 }
6068 Parser.Lex(); // Eat the comma.
6069 const MCExpr *DummyNumber;
6070 int64_t DummyNumberVal;
6071 // If the user was explicitly trying to use the extended version,
6072 // we still give helpful extension-related error messages.
6073 if (Parser.parseExpression(DummyNumber)) {
6074 reportParseError("expected number after comma");
6075 return false;
6076 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00006077 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006078 reportParseError("expected an absolute expression after comma");
6079 return false;
6080 }
6081 }
6082
6083 // If this is not the end of the statement, report an error.
6084 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6085 reportParseError("unexpected token, expected end of statement");
6086 return false;
6087 }
6088
Jim Grosbach6f482002015-05-18 18:43:14 +00006089 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006090
6091 getTargetStreamer().emitDirectiveEnt(*Sym);
6092 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006093 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006094 return false;
6095 }
6096
Jack Carter07c818d2013-01-25 01:31:34 +00006097 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006098 StringRef SymbolName;
6099
6100 if (Parser.parseIdentifier(SymbolName)) {
6101 reportParseError("expected identifier after .end");
6102 return false;
6103 }
6104
6105 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6106 reportParseError("unexpected token, expected end of statement");
6107 return false;
6108 }
6109
6110 if (CurrentFn == nullptr) {
6111 reportParseError(".end used without .ent");
6112 return false;
6113 }
6114
6115 if ((SymbolName != CurrentFn->getName())) {
6116 reportParseError(".end symbol does not match .ent symbol");
6117 return false;
6118 }
6119
6120 getTargetStreamer().emitDirectiveEnd(SymbolName);
6121 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006122 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006123 return false;
6124 }
6125
Jack Carter07c818d2013-01-25 01:31:34 +00006126 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006127 // .frame $stack_reg, frame_size_in_bytes, $return_reg
6128 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00006129 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006130 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6131 reportParseError("expected stack register");
6132 return false;
6133 }
6134
6135 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6136 if (!StackRegOpnd.isGPRAsmReg()) {
6137 reportParseError(StackRegOpnd.getStartLoc(),
6138 "expected general purpose register");
6139 return false;
6140 }
6141 unsigned StackReg = StackRegOpnd.getGPR32Reg();
6142
6143 if (Parser.getTok().is(AsmToken::Comma))
6144 Parser.Lex();
6145 else {
6146 reportParseError("unexpected token, expected comma");
6147 return false;
6148 }
6149
6150 // Parse the frame size.
6151 const MCExpr *FrameSize;
6152 int64_t FrameSizeVal;
6153
6154 if (Parser.parseExpression(FrameSize)) {
6155 reportParseError("expected frame size value");
6156 return false;
6157 }
6158
Jim Grosbach13760bd2015-05-30 01:25:56 +00006159 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006160 reportParseError("frame size not an absolute expression");
6161 return false;
6162 }
6163
6164 if (Parser.getTok().is(AsmToken::Comma))
6165 Parser.Lex();
6166 else {
6167 reportParseError("unexpected token, expected comma");
6168 return false;
6169 }
6170
6171 // Parse the return register.
6172 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00006173 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006174 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6175 reportParseError("expected return register");
6176 return false;
6177 }
6178
6179 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6180 if (!ReturnRegOpnd.isGPRAsmReg()) {
6181 reportParseError(ReturnRegOpnd.getStartLoc(),
6182 "expected general purpose register");
6183 return false;
6184 }
6185
6186 // If this is not the end of the statement, report an error.
6187 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6188 reportParseError("unexpected token, expected end of statement");
6189 return false;
6190 }
6191
6192 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
6193 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006194 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006195 return false;
6196 }
6197
Jack Carter07c818d2013-01-25 01:31:34 +00006198 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00006199 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00006200 }
6201
Daniel Sandersd97a6342014-08-13 10:07:34 +00006202 if (IDVal == ".mask" || IDVal == ".fmask") {
6203 // .mask bitmask, frame_offset
6204 // bitmask: One bit for each register used.
6205 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
6206 // first register is expected to be saved.
6207 // Examples:
6208 // .mask 0x80000000, -4
6209 // .fmask 0x80000000, -4
6210 //
Jack Carterbe332172012-09-07 00:48:02 +00006211
Daniel Sandersd97a6342014-08-13 10:07:34 +00006212 // Parse the bitmask
6213 const MCExpr *BitMask;
6214 int64_t BitMaskVal;
6215
6216 if (Parser.parseExpression(BitMask)) {
6217 reportParseError("expected bitmask value");
6218 return false;
6219 }
6220
Jim Grosbach13760bd2015-05-30 01:25:56 +00006221 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006222 reportParseError("bitmask not an absolute expression");
6223 return false;
6224 }
6225
6226 if (Parser.getTok().is(AsmToken::Comma))
6227 Parser.Lex();
6228 else {
6229 reportParseError("unexpected token, expected comma");
6230 return false;
6231 }
6232
6233 // Parse the frame_offset
6234 const MCExpr *FrameOffset;
6235 int64_t FrameOffsetVal;
6236
6237 if (Parser.parseExpression(FrameOffset)) {
6238 reportParseError("expected frame offset value");
6239 return false;
6240 }
6241
Jim Grosbach13760bd2015-05-30 01:25:56 +00006242 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006243 reportParseError("frame offset not an absolute expression");
6244 return false;
6245 }
6246
6247 // If this is not the end of the statement, report an error.
6248 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6249 reportParseError("unexpected token, expected end of statement");
6250 return false;
6251 }
6252
6253 if (IDVal == ".mask")
6254 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
6255 else
6256 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00006257 return false;
6258 }
6259
Matheus Almeida0051f2d2014-04-16 15:48:55 +00006260 if (IDVal == ".nan")
6261 return parseDirectiveNaN();
6262
Jack Carter07c818d2013-01-25 01:31:34 +00006263 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00006264 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00006265 return false;
6266 }
6267
Rafael Espindolab59fb732014-03-28 18:50:26 +00006268 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00006269 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00006270 return false;
6271 }
6272
Jack Carter07c818d2013-01-25 01:31:34 +00006273 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00006274 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00006275 return false;
6276 }
6277
Scott Egertond1aeb052016-02-15 16:11:51 +00006278 if (IDVal == ".hword") {
6279 parseDataDirective(2, DirectiveID.getLoc());
6280 return false;
6281 }
6282
Jack Carter0cd3c192014-01-06 23:27:31 +00006283 if (IDVal == ".option")
6284 return parseDirectiveOption();
6285
6286 if (IDVal == ".abicalls") {
6287 getTargetStreamer().emitDirectiveAbiCalls();
6288 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006289 Error(Parser.getTok().getLoc(),
6290 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00006291 // Clear line
6292 Parser.eatToEndOfStatement();
6293 }
6294 return false;
6295 }
6296
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006297 if (IDVal == ".cpsetup")
6298 return parseDirectiveCPSetup();
6299
Daniel Sandersf173dda2015-09-22 10:50:09 +00006300 if (IDVal == ".cpreturn")
6301 return parseDirectiveCPReturn();
6302
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006303 if (IDVal == ".module")
6304 return parseDirectiveModule();
6305
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00006306 if (IDVal == ".llvm_internal_mips_reallow_module_directive")
6307 return parseInternalDirectiveReallowModule();
6308
Toma Tabacu9ca50962015-04-16 09:53:47 +00006309 if (IDVal == ".insn")
6310 return parseInsnDirective();
6311
Simon Atanasyanbe186202016-02-11 06:45:54 +00006312 if (IDVal == ".sbss")
6313 return parseSSectionDirective(IDVal, ELF::SHT_NOBITS);
6314 if (IDVal == ".sdata")
6315 return parseSSectionDirective(IDVal, ELF::SHT_PROGBITS);
6316
Rafael Espindola870c4e92012-01-11 03:56:41 +00006317 return true;
6318}
6319
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00006320bool MipsAsmParser::parseInternalDirectiveReallowModule() {
6321 // If this is not the end of the statement, report an error.
6322 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6323 reportParseError("unexpected token, expected end of statement");
6324 return false;
6325 }
6326
6327 getTargetStreamer().reallowModuleDirective();
6328
6329 getParser().Lex(); // Eat EndOfStatement token.
6330 return false;
6331}
6332
Rafael Espindola870c4e92012-01-11 03:56:41 +00006333extern "C" void LLVMInitializeMipsAsmParser() {
6334 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
6335 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
6336 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
6337 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
6338}
Jack Carterb4dbc172012-09-05 23:34:03 +00006339
6340#define GET_REGISTER_MATCHER
6341#define GET_MATCHER_IMPLEMENTATION
6342#include "MipsGenAsmMatcher.inc"