blob: 42a0c96b8765b24207db02c916a3c815e12e006c [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 }
Daniel Sanders97297772016-03-22 14:40:00 +00001083 template <unsigned Bits, unsigned ShiftLeftAmount>
1084 bool isScaledSImm() const {
1085 return isConstantImm() &&
1086 isShiftedInt<Bits, ShiftLeftAmount>(getConstantImm());
1087 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001088 bool isRegList16() const {
1089 if (!isRegList())
1090 return false;
1091
1092 int Size = RegList.List->size();
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001093 if (Size < 2 || Size > 5)
1094 return false;
1095
1096 unsigned R0 = RegList.List->front();
1097 unsigned R1 = RegList.List->back();
1098 if (!((R0 == Mips::S0 && R1 == Mips::RA) ||
1099 (R0 == Mips::S0_64 && R1 == Mips::RA_64)))
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001100 return false;
1101
1102 int PrevReg = *RegList.List->begin();
1103 for (int i = 1; i < Size - 1; i++) {
1104 int Reg = (*(RegList.List))[i];
1105 if ( Reg != PrevReg + 1)
1106 return false;
1107 PrevReg = Reg;
1108 }
1109
1110 return true;
1111 }
Vladimir Medic2b953d02013-10-01 09:48:56 +00001112 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001113 bool isLSAImm() const {
1114 if (!isConstantImm())
1115 return false;
1116 int64_t Val = getConstantImm();
1117 return 1 <= Val && Val <= 4;
1118 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001119 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001120 bool isMovePRegPair() const {
1121 if (Kind != k_RegList || RegList.List->size() != 2)
1122 return false;
1123
1124 unsigned R0 = RegList.List->front();
1125 unsigned R1 = RegList.List->back();
1126
1127 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
1128 (R0 == Mips::A1 && R1 == Mips::A3) ||
1129 (R0 == Mips::A2 && R1 == Mips::A3) ||
1130 (R0 == Mips::A0 && R1 == Mips::S5) ||
1131 (R0 == Mips::A0 && R1 == Mips::S6) ||
1132 (R0 == Mips::A0 && R1 == Mips::A1) ||
1133 (R0 == Mips::A0 && R1 == Mips::A2) ||
1134 (R0 == Mips::A0 && R1 == Mips::A3))
1135 return true;
1136
1137 return false;
1138 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001139
1140 StringRef getToken() const {
1141 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001142 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001143 }
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001144 bool isRegPair() const { return Kind == k_RegPair; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001145
Craig Topper56c590a2014-04-29 07:58:02 +00001146 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001147 // As a special case until we sort out the definition of div/divu, pretend
1148 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
1149 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1150 RegIdx.Kind & RegKind_GPR)
1151 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001152
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001153 assert(Kind == k_PhysRegister && "Invalid access!");
1154 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +00001155 }
1156
Jack Carterb4dbc172012-09-05 23:34:03 +00001157 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001158 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001159 return Imm.Val;
1160 }
1161
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001162 int64_t getConstantImm() const {
1163 const MCExpr *Val = getImm();
1164 return static_cast<const MCConstantExpr *>(Val)->getValue();
1165 }
1166
1167 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001168 assert((Kind == k_Memory) && "Invalid access!");
1169 return Mem.Base;
1170 }
1171
1172 const MCExpr *getMemOff() const {
1173 assert((Kind == k_Memory) && "Invalid access!");
1174 return Mem.Off;
1175 }
1176
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001177 int64_t getConstantMemOff() const {
1178 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1179 }
1180
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001181 const SmallVectorImpl<unsigned> &getRegList() const {
1182 assert((Kind == k_RegList) && "Invalid access!");
1183 return *(RegList.List);
1184 }
1185
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001186 unsigned getRegPair() const {
1187 assert((Kind == k_RegPair) && "Invalid access!");
1188 return RegIdx.Index;
1189 }
1190
David Blaikie960ea3f2014-06-08 16:18:35 +00001191 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1192 MipsAsmParser &Parser) {
1193 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001194 Op->Tok.Data = Str.data();
1195 Op->Tok.Length = Str.size();
1196 Op->StartLoc = S;
1197 Op->EndLoc = S;
1198 return Op;
1199 }
1200
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001201 /// Create a numeric register (e.g. $1). The exact register remains
1202 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001203 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001204 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001205 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001206 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001207 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001208 }
1209
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001210 /// Create a register that is definitely a GPR.
1211 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001212 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001213 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001214 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001215 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001216 }
1217
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001218 /// Create a register that is definitely a FGR.
1219 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001220 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001221 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001222 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001223 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
1224 }
1225
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001226 /// Create a register that is definitely a HWReg.
1227 /// This is typically only used for named registers such as $hwr_cpunum.
1228 static std::unique_ptr<MipsOperand>
1229 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
1230 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1231 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
1232 }
1233
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001234 /// Create a register that is definitely an FCC.
1235 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001236 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001237 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001238 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001239 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
1240 }
1241
1242 /// Create a register that is definitely an ACC.
1243 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001244 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001245 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001246 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001247 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
1248 }
1249
1250 /// Create a register that is definitely an MSA128.
1251 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001252 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001253 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001254 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001255 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
1256 }
1257
1258 /// Create a register that is definitely an MSACtrl.
1259 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001260 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001261 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001262 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001263 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
1264 }
1265
David Blaikie960ea3f2014-06-08 16:18:35 +00001266 static std::unique_ptr<MipsOperand>
1267 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1268 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001269 Op->Imm.Val = Val;
1270 Op->StartLoc = S;
1271 Op->EndLoc = E;
1272 return Op;
1273 }
1274
David Blaikie960ea3f2014-06-08 16:18:35 +00001275 static std::unique_ptr<MipsOperand>
1276 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1277 SMLoc E, MipsAsmParser &Parser) {
1278 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1279 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001280 Op->Mem.Off = Off;
1281 Op->StartLoc = S;
1282 Op->EndLoc = E;
1283 return Op;
1284 }
1285
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001286 static std::unique_ptr<MipsOperand>
1287 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1288 MipsAsmParser &Parser) {
1289 assert (Regs.size() > 0 && "Empty list not allowed");
1290
1291 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001292 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001293 Op->StartLoc = StartLoc;
1294 Op->EndLoc = EndLoc;
1295 return Op;
1296 }
1297
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001298 static std::unique_ptr<MipsOperand>
1299 CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1300 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
1301 Op->RegIdx.Index = RegNo;
1302 Op->StartLoc = S;
1303 Op->EndLoc = E;
1304 return Op;
1305 }
1306
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001307 bool isGPRAsmReg() const {
1308 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001309 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001310 bool isMM16AsmReg() const {
1311 if (!(isRegIdx() && RegIdx.Kind))
1312 return false;
1313 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1314 || RegIdx.Index == 16 || RegIdx.Index == 17);
1315 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001316 bool isMM16AsmRegZero() const {
1317 if (!(isRegIdx() && RegIdx.Kind))
1318 return false;
1319 return (RegIdx.Index == 0 ||
1320 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1321 RegIdx.Index == 17);
1322 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001323 bool isMM16AsmRegMoveP() const {
1324 if (!(isRegIdx() && RegIdx.Kind))
1325 return false;
1326 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1327 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1328 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001329 bool isFGRAsmReg() const {
1330 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1331 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001332 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001333 bool isHWRegsAsmReg() const {
1334 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001335 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001336 bool isCCRAsmReg() const {
1337 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001338 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001339 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001340 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1341 return false;
1342 if (!AsmParser.hasEightFccRegisters())
1343 return RegIdx.Index == 0;
1344 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001345 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001346 bool isACCAsmReg() const {
1347 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001348 }
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001349 bool isCOP0AsmReg() const {
1350 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1351 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001352 bool isCOP2AsmReg() const {
1353 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001354 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001355 bool isCOP3AsmReg() const {
1356 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1357 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001358 bool isMSA128AsmReg() const {
1359 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001360 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001361 bool isMSACtrlAsmReg() const {
1362 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001363 }
1364
Jack Carterb4dbc172012-09-05 23:34:03 +00001365 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001366 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001367 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001368 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001369
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001370 virtual ~MipsOperand() {
1371 switch (Kind) {
1372 case k_Immediate:
1373 break;
1374 case k_Memory:
1375 delete Mem.Base;
1376 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001377 case k_RegList:
1378 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001379 case k_PhysRegister:
1380 case k_RegisterIndex:
1381 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001382 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001383 break;
1384 }
1385 }
1386
Craig Topper56c590a2014-04-29 07:58:02 +00001387 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001388 switch (Kind) {
1389 case k_Immediate:
1390 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001391 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001392 OS << ">";
1393 break;
1394 case k_Memory:
1395 OS << "Mem<";
1396 Mem.Base->print(OS);
1397 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001398 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001399 OS << ">";
1400 break;
1401 case k_PhysRegister:
1402 OS << "PhysReg<" << PhysReg.Num << ">";
1403 break;
1404 case k_RegisterIndex:
1405 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1406 break;
1407 case k_Token:
1408 OS << Tok.Data;
1409 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001410 case k_RegList:
1411 OS << "RegList< ";
1412 for (auto Reg : (*RegList.List))
1413 OS << Reg << " ";
1414 OS << ">";
1415 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001416 case k_RegPair:
1417 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1418 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001419 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001420 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001421}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001422} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001423
Jack Carter9e65aa32013-03-22 00:05:30 +00001424namespace llvm {
1425extern const MCInstrDesc MipsInsts[];
1426}
1427static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1428 return MipsInsts[Opcode];
1429}
1430
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001431static bool hasShortDelaySlot(unsigned Opcode) {
1432 switch (Opcode) {
1433 case Mips::JALS_MM:
1434 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001435 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001436 case Mips::BGEZALS_MM:
1437 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001438 return true;
1439 default:
1440 return false;
1441 }
1442}
1443
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001444static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1445 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1446 return &SRExpr->getSymbol();
1447 }
1448
1449 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1450 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1451 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1452
1453 if (LHSSym)
1454 return LHSSym;
1455
1456 if (RHSSym)
1457 return RHSSym;
1458
1459 return nullptr;
1460 }
1461
1462 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1463 return getSingleMCSymbol(UExpr->getSubExpr());
1464
1465 return nullptr;
1466}
1467
1468static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1469 if (isa<MCSymbolRefExpr>(Expr))
1470 return 1;
1471
1472 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1473 return countMCSymbolRefExpr(BExpr->getLHS()) +
1474 countMCSymbolRefExpr(BExpr->getRHS());
1475
1476 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1477 return countMCSymbolRefExpr(UExpr->getSubExpr());
1478
1479 return 0;
1480}
1481
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001482namespace {
1483void emitRX(unsigned Opcode, unsigned Reg0, MCOperand Op1, SMLoc IDLoc,
1484 SmallVectorImpl<MCInst> &Instructions) {
1485 MCInst tmpInst;
1486 tmpInst.setOpcode(Opcode);
1487 tmpInst.addOperand(MCOperand::createReg(Reg0));
1488 tmpInst.addOperand(Op1);
1489 tmpInst.setLoc(IDLoc);
1490 Instructions.push_back(tmpInst);
1491}
1492
1493void emitRI(unsigned Opcode, unsigned Reg0, int32_t Imm, SMLoc IDLoc,
1494 SmallVectorImpl<MCInst> &Instructions) {
1495 emitRX(Opcode, Reg0, MCOperand::createImm(Imm), IDLoc, Instructions);
1496}
1497
1498void emitRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, SMLoc IDLoc,
1499 SmallVectorImpl<MCInst> &Instructions) {
1500 emitRX(Opcode, Reg0, MCOperand::createReg(Reg1), IDLoc, Instructions);
1501}
1502
1503void emitII(unsigned Opcode, int16_t Imm1, int16_t Imm2, SMLoc IDLoc,
1504 SmallVectorImpl<MCInst> &Instructions) {
1505 MCInst tmpInst;
1506 tmpInst.setOpcode(Opcode);
1507 tmpInst.addOperand(MCOperand::createImm(Imm1));
1508 tmpInst.addOperand(MCOperand::createImm(Imm2));
1509 tmpInst.setLoc(IDLoc);
1510 Instructions.push_back(tmpInst);
1511}
1512
1513void emitR(unsigned Opcode, unsigned Reg0, SMLoc IDLoc,
1514 SmallVectorImpl<MCInst> &Instructions) {
1515 MCInst tmpInst;
1516 tmpInst.setOpcode(Opcode);
1517 tmpInst.addOperand(MCOperand::createReg(Reg0));
1518 tmpInst.setLoc(IDLoc);
1519 Instructions.push_back(tmpInst);
1520}
1521
1522void emitRRX(unsigned Opcode, unsigned Reg0, unsigned Reg1, MCOperand Op2,
1523 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1524 MCInst tmpInst;
1525 tmpInst.setOpcode(Opcode);
1526 tmpInst.addOperand(MCOperand::createReg(Reg0));
1527 tmpInst.addOperand(MCOperand::createReg(Reg1));
1528 tmpInst.addOperand(Op2);
1529 tmpInst.setLoc(IDLoc);
1530 Instructions.push_back(tmpInst);
1531}
1532
1533void emitRRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, unsigned Reg2,
1534 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1535 emitRRX(Opcode, Reg0, Reg1, MCOperand::createReg(Reg2), IDLoc,
1536 Instructions);
1537}
1538
1539void emitRRI(unsigned Opcode, unsigned Reg0, unsigned Reg1, int16_t Imm,
1540 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1541 emitRRX(Opcode, Reg0, Reg1, MCOperand::createImm(Imm), IDLoc,
1542 Instructions);
1543}
1544
1545void emitAppropriateDSLL(unsigned DstReg, unsigned SrcReg, int16_t ShiftAmount,
1546 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1547 if (ShiftAmount >= 32) {
1548 emitRRI(Mips::DSLL32, DstReg, SrcReg, ShiftAmount - 32, IDLoc,
1549 Instructions);
1550 return;
1551 }
1552
1553 emitRRI(Mips::DSLL, DstReg, SrcReg, ShiftAmount, IDLoc, Instructions);
1554}
1555} // end anonymous namespace.
1556
Jack Carter9e65aa32013-03-22 00:05:30 +00001557bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001558 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001559 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001560 bool ExpandedJalSym = false;
Daniel Sandersa771fef2014-03-24 14:05:39 +00001561
Jack Carter9e65aa32013-03-22 00:05:30 +00001562 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001563
1564 if (MCID.isBranch() || MCID.isCall()) {
1565 const unsigned Opcode = Inst.getOpcode();
1566 MCOperand Offset;
1567
1568 switch (Opcode) {
1569 default:
1570 break;
Kai Nackee0245392015-01-27 19:11:28 +00001571 case Mips::BBIT0:
1572 case Mips::BBIT032:
1573 case Mips::BBIT1:
1574 case Mips::BBIT132:
1575 assert(hasCnMips() && "instruction only valid for octeon cpus");
1576 // Fall through
1577
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001578 case Mips::BEQ:
1579 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001580 case Mips::BEQ_MM:
1581 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001582 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001583 Offset = Inst.getOperand(2);
1584 if (!Offset.isImm())
1585 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001586 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001587 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001588 if (OffsetToAlignment(Offset.getImm(),
1589 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001590 return Error(IDLoc, "branch to misaligned address");
1591 break;
1592 case Mips::BGEZ:
1593 case Mips::BGTZ:
1594 case Mips::BLEZ:
1595 case Mips::BLTZ:
1596 case Mips::BGEZAL:
1597 case Mips::BLTZAL:
1598 case Mips::BC1F:
1599 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001600 case Mips::BGEZ_MM:
1601 case Mips::BGTZ_MM:
1602 case Mips::BLEZ_MM:
1603 case Mips::BLTZ_MM:
1604 case Mips::BGEZAL_MM:
1605 case Mips::BLTZAL_MM:
1606 case Mips::BC1F_MM:
1607 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001608 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001609 Offset = Inst.getOperand(1);
1610 if (!Offset.isImm())
1611 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001612 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001613 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001614 if (OffsetToAlignment(Offset.getImm(),
1615 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001616 return Error(IDLoc, "branch to misaligned address");
1617 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001618 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001619 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001620 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001621 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001622 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1623 Offset = Inst.getOperand(1);
1624 if (!Offset.isImm())
1625 break; // We'll deal with this situation later on when applying fixups.
Craig Topper55b1f292015-10-10 20:17:07 +00001626 if (!isInt<8>(Offset.getImm()))
Jozef Kolek9761e962015-01-12 12:03:34 +00001627 return Error(IDLoc, "branch target out of range");
1628 if (OffsetToAlignment(Offset.getImm(), 2LL))
1629 return Error(IDLoc, "branch to misaligned address");
1630 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001631 }
1632 }
1633
Daniel Sandersa84989a2014-06-16 13:25:35 +00001634 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1635 // We still accept it but it is a normal nop.
1636 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1637 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1638 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1639 "nop instruction");
1640 }
1641
Kai Nackee0245392015-01-27 19:11:28 +00001642 if (hasCnMips()) {
1643 const unsigned Opcode = Inst.getOpcode();
1644 MCOperand Opnd;
1645 int Imm;
1646
1647 switch (Opcode) {
1648 default:
1649 break;
1650
1651 case Mips::BBIT0:
1652 case Mips::BBIT032:
1653 case Mips::BBIT1:
1654 case Mips::BBIT132:
1655 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1656 // The offset is handled above
1657 Opnd = Inst.getOperand(1);
1658 if (!Opnd.isImm())
1659 return Error(IDLoc, "expected immediate operand kind");
1660 Imm = Opnd.getImm();
1661 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1662 Opcode == Mips::BBIT1 ? 63 : 31))
1663 return Error(IDLoc, "immediate operand value out of range");
1664 if (Imm > 31) {
1665 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1666 : Mips::BBIT132);
1667 Inst.getOperand(1).setImm(Imm - 32);
1668 }
1669 break;
1670
Kai Nackee0245392015-01-27 19:11:28 +00001671 case Mips::SEQi:
1672 case Mips::SNEi:
1673 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1674 Opnd = Inst.getOperand(2);
1675 if (!Opnd.isImm())
1676 return Error(IDLoc, "expected immediate operand kind");
1677 Imm = Opnd.getImm();
1678 if (!isInt<10>(Imm))
1679 return Error(IDLoc, "immediate operand value out of range");
1680 break;
1681 }
1682 }
1683
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001684 // This expansion is not in a function called by tryExpandInstruction()
1685 // because the pseudo-instruction doesn't have a distinct opcode.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001686 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
1687 inPicMode()) {
1688 warnIfNoMacro(IDLoc);
1689
1690 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
1691
1692 // We can do this expansion if there's only 1 symbol in the argument
1693 // expression.
1694 if (countMCSymbolRefExpr(JalExpr) > 1)
1695 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
1696
1697 // FIXME: This is checking the expression can be handled by the later stages
1698 // of the assembler. We ought to leave it to those later stages but
1699 // we can't do that until we stop evaluateRelocExpr() rewriting the
1700 // expressions into non-equivalent forms.
1701 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
1702
1703 // FIXME: Add support for label+offset operands (currently causes an error).
1704 // FIXME: Add support for forward-declared local symbols.
1705 // FIXME: Add expansion for when the LargeGOT option is enabled.
1706 if (JalSym->isInSection() || JalSym->isTemporary()) {
1707 if (isABI_O32()) {
1708 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001709 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001710 // R_(MICRO)MIPS_GOT16 label
1711 // addiu $25, $25, 0
1712 // R_(MICRO)MIPS_LO16 label
1713 // jalr $25
1714 const MCExpr *Got16RelocExpr = evaluateRelocExpr(JalExpr, "got");
1715 const MCExpr *Lo16RelocExpr = evaluateRelocExpr(JalExpr, "lo");
1716
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001717 emitRRX(Mips::LW, Mips::T9, Mips::GP,
1718 MCOperand::createExpr(Got16RelocExpr), IDLoc, Instructions);
1719 emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
1720 MCOperand::createExpr(Lo16RelocExpr), IDLoc, Instructions);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001721 } else if (isABI_N32() || isABI_N64()) {
1722 // If it's a local symbol and the N32/N64 ABIs are being used,
1723 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001724 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001725 // R_(MICRO)MIPS_GOT_DISP label
1726 // jalr $25
1727 const MCExpr *GotDispRelocExpr = evaluateRelocExpr(JalExpr, "got_disp");
1728
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001729 emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
1730 MCOperand::createExpr(GotDispRelocExpr), IDLoc, Instructions);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001731 }
1732 } else {
Daniel Sandersb7002032015-11-20 13:16:35 +00001733 // If it's an external/weak symbol, we expand to:
1734 // lw/ld $25, 0($gp)
1735 // R_(MICRO)MIPS_CALL16 label
1736 // jalr $25
1737 const MCExpr *Call16RelocExpr = evaluateRelocExpr(JalExpr, "call16");
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001738
Daniel Sandersb7002032015-11-20 13:16:35 +00001739 emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
1740 MCOperand::createExpr(Call16RelocExpr), IDLoc, Instructions);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001741 }
1742
1743 MCInst JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001744 if (IsCpRestoreSet && inMicroMipsMode())
1745 JalrInst.setOpcode(Mips::JALRS_MM);
1746 else
1747 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001748 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
1749 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
1750
1751 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
1752 // This relocation is supposed to be an optimization hint for the linker
1753 // and is not necessary for correctness.
1754
1755 Inst = JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001756 ExpandedJalSym = true;
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001757 }
1758
Jack Carter9e65aa32013-03-22 00:05:30 +00001759 if (MCID.mayLoad() || MCID.mayStore()) {
1760 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001761 // reference or immediate we may have to expand instructions.
1762 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001763 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001764 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1765 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001766 MCOperand &Op = Inst.getOperand(i);
1767 if (Op.isImm()) {
1768 int MemOffset = Op.getImm();
1769 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001770 // Offset can't exceed 16bit value.
1771 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001772 return false;
1773 }
1774 } else if (Op.isExpr()) {
1775 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001776 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001777 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001778 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001779 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001780 // Expand symbol.
1781 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001782 return false;
1783 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001784 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001785 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001786 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001787 }
1788 }
1789 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001790 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001791 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001792
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001793 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001794 if (MCID.mayLoad()) {
1795 // Try to create 16-bit GP relative load instruction.
1796 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1797 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1798 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1799 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1800 MCOperand &Op = Inst.getOperand(i);
1801 if (Op.isImm()) {
1802 int MemOffset = Op.getImm();
1803 MCOperand &DstReg = Inst.getOperand(0);
1804 MCOperand &BaseReg = Inst.getOperand(1);
Craig Topper55b1f292015-10-10 20:17:07 +00001805 if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&
Jozef Koleke10a02e2015-01-28 17:27:26 +00001806 getContext().getRegisterInfo()->getRegClass(
1807 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00001808 (BaseReg.getReg() == Mips::GP ||
1809 BaseReg.getReg() == Mips::GP_64)) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001810
1811 emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
1812 IDLoc, Instructions);
Jozef Koleke10a02e2015-01-28 17:27:26 +00001813 return false;
1814 }
1815 }
1816 }
1817 } // for
1818 } // if load
1819
1820 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1821
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001822 MCOperand Opnd;
1823 int Imm;
1824
1825 switch (Inst.getOpcode()) {
1826 default:
1827 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001828 case Mips::ADDIUSP_MM:
1829 Opnd = Inst.getOperand(0);
1830 if (!Opnd.isImm())
1831 return Error(IDLoc, "expected immediate operand kind");
1832 Imm = Opnd.getImm();
1833 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1834 Imm % 4 != 0)
1835 return Error(IDLoc, "immediate operand value out of range");
1836 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001837 case Mips::SLL16_MM:
1838 case Mips::SRL16_MM:
1839 Opnd = Inst.getOperand(2);
1840 if (!Opnd.isImm())
1841 return Error(IDLoc, "expected immediate operand kind");
1842 Imm = Opnd.getImm();
1843 if (Imm < 1 || Imm > 8)
1844 return Error(IDLoc, "immediate operand value out of range");
1845 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001846 case Mips::LI16_MM:
1847 Opnd = Inst.getOperand(1);
1848 if (!Opnd.isImm())
1849 return Error(IDLoc, "expected immediate operand kind");
1850 Imm = Opnd.getImm();
1851 if (Imm < -1 || Imm > 126)
1852 return Error(IDLoc, "immediate operand value out of range");
1853 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001854 case Mips::ADDIUR2_MM:
1855 Opnd = Inst.getOperand(2);
1856 if (!Opnd.isImm())
1857 return Error(IDLoc, "expected immediate operand kind");
1858 Imm = Opnd.getImm();
1859 if (!(Imm == 1 || Imm == -1 ||
1860 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1861 return Error(IDLoc, "immediate operand value out of range");
1862 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001863 case Mips::ANDI16_MM:
1864 Opnd = Inst.getOperand(2);
1865 if (!Opnd.isImm())
1866 return Error(IDLoc, "expected immediate operand kind");
1867 Imm = Opnd.getImm();
1868 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1869 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1870 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1871 return Error(IDLoc, "immediate operand value out of range");
1872 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001873 case Mips::LBU16_MM:
1874 Opnd = Inst.getOperand(2);
1875 if (!Opnd.isImm())
1876 return Error(IDLoc, "expected immediate operand kind");
1877 Imm = Opnd.getImm();
1878 if (Imm < -1 || Imm > 14)
1879 return Error(IDLoc, "immediate operand value out of range");
1880 break;
1881 case Mips::SB16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001882 case Mips::SB16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001883 Opnd = Inst.getOperand(2);
1884 if (!Opnd.isImm())
1885 return Error(IDLoc, "expected immediate operand kind");
1886 Imm = Opnd.getImm();
1887 if (Imm < 0 || Imm > 15)
1888 return Error(IDLoc, "immediate operand value out of range");
1889 break;
1890 case Mips::LHU16_MM:
1891 case Mips::SH16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001892 case Mips::SH16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001893 Opnd = Inst.getOperand(2);
1894 if (!Opnd.isImm())
1895 return Error(IDLoc, "expected immediate operand kind");
1896 Imm = Opnd.getImm();
1897 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1898 return Error(IDLoc, "immediate operand value out of range");
1899 break;
1900 case Mips::LW16_MM:
1901 case Mips::SW16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001902 case Mips::SW16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001903 Opnd = Inst.getOperand(2);
1904 if (!Opnd.isImm())
1905 return Error(IDLoc, "expected immediate operand kind");
1906 Imm = Opnd.getImm();
1907 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1908 return Error(IDLoc, "immediate operand value out of range");
1909 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001910 case Mips::ADDIUPC_MM:
1911 MCOperand Opnd = Inst.getOperand(1);
1912 if (!Opnd.isImm())
1913 return Error(IDLoc, "expected immediate operand kind");
1914 int Imm = Opnd.getImm();
Craig Topper55b1f292015-10-10 20:17:07 +00001915 if ((Imm % 4 != 0) || !isInt<25>(Imm))
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001916 return Error(IDLoc, "immediate operand value out of range");
1917 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001918 }
1919 }
1920
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001921 MacroExpanderResultTy ExpandResult =
1922 tryExpandInstruction(Inst, IDLoc, Instructions);
1923 switch (ExpandResult) {
1924 case MER_NotAMacro:
Jack Carter9e65aa32013-03-22 00:05:30 +00001925 Instructions.push_back(Inst);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001926 break;
1927 case MER_Success:
1928 break;
1929 case MER_Fail:
1930 return true;
1931 }
Jack Carter9e65aa32013-03-22 00:05:30 +00001932
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001933 // If this instruction has a delay slot and .set reorder is active,
1934 // emit a NOP after it.
1935 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
1936 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1937
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001938 if ((Inst.getOpcode() == Mips::JalOneReg ||
1939 Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
1940 isPicAndNotNxxAbi()) {
1941 if (IsCpRestoreSet) {
1942 // We need a NOP between the JALR and the LW:
1943 // If .set reorder has been used, we've already emitted a NOP.
1944 // If .set noreorder has been used, we need to emit a NOP at this point.
1945 if (!AssemblerOptions.back()->isReorder())
1946 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1947
1948 // Load the $gp from the stack.
1949 SmallVector<MCInst, 3> LoadInsts;
1950 createCpRestoreMemOp(true /*IsLoad*/, CpRestoreOffset /*StackOffset*/,
1951 IDLoc, LoadInsts);
1952
1953 for (const MCInst &Inst : LoadInsts)
1954 Instructions.push_back(Inst);
1955
1956 } else
1957 Warning(IDLoc, "no .cprestore used in PIC mode");
1958 }
1959
Jack Carter9e65aa32013-03-22 00:05:30 +00001960 return false;
1961}
1962
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001963MipsAsmParser::MacroExpanderResultTy
1964MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
1965 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001966 switch (Inst.getOpcode()) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001967 default:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001968 return MER_NotAMacro;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001969 case Mips::LoadImm32:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001970 return expandLoadImm(Inst, true, IDLoc, Instructions) ? MER_Fail
1971 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001972 case Mips::LoadImm64:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001973 return expandLoadImm(Inst, false, IDLoc, Instructions) ? MER_Fail
1974 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001975 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001976 case Mips::LoadAddrImm64:
1977 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1978 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
1979 "expected immediate operand kind");
1980
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001981 return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,
1982 Inst.getOperand(1),
1983 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,
1984 Instructions)
1985 ? MER_Fail
1986 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001987 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001988 case Mips::LoadAddrReg64:
1989 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1990 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1991 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
1992 "expected immediate operand kind");
1993
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001994 return expandLoadAddress(Inst.getOperand(0).getReg(),
1995 Inst.getOperand(1).getReg(), Inst.getOperand(2),
1996 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,
1997 Instructions)
1998 ? MER_Fail
1999 : MER_Success;
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002000 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00002001 case Mips::B_MMR6_Pseudo:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002002 return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions) ? MER_Fail
2003 : MER_Success;
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002004 case Mips::SWM_MM:
2005 case Mips::LWM_MM:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002006 return expandLoadStoreMultiple(Inst, IDLoc, Instructions) ? MER_Fail
2007 : MER_Success;
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002008 case Mips::JalOneReg:
2009 case Mips::JalTwoReg:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002010 return expandJalWithRegs(Inst, IDLoc, Instructions) ? MER_Fail
2011 : MER_Success;
Toma Tabacue1e460d2015-06-11 10:36:10 +00002012 case Mips::BneImm:
2013 case Mips::BeqImm:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002014 return expandBranchImm(Inst, IDLoc, Instructions) ? MER_Fail : MER_Success;
Toma Tabacu1a108322015-06-17 13:20:24 +00002015 case Mips::BLT:
2016 case Mips::BLE:
2017 case Mips::BGE:
2018 case Mips::BGT:
2019 case Mips::BLTU:
2020 case Mips::BLEU:
2021 case Mips::BGEU:
2022 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002023 case Mips::BLTL:
2024 case Mips::BLEL:
2025 case Mips::BGEL:
2026 case Mips::BGTL:
2027 case Mips::BLTUL:
2028 case Mips::BLEUL:
2029 case Mips::BGEUL:
2030 case Mips::BGTUL:
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002031 case Mips::BLTImmMacro:
2032 case Mips::BLEImmMacro:
2033 case Mips::BGEImmMacro:
2034 case Mips::BGTImmMacro:
2035 case Mips::BLTUImmMacro:
2036 case Mips::BLEUImmMacro:
2037 case Mips::BGEUImmMacro:
2038 case Mips::BGTUImmMacro:
2039 case Mips::BLTLImmMacro:
2040 case Mips::BLELImmMacro:
2041 case Mips::BGELImmMacro:
2042 case Mips::BGTLImmMacro:
2043 case Mips::BLTULImmMacro:
2044 case Mips::BLEULImmMacro:
2045 case Mips::BGEULImmMacro:
2046 case Mips::BGTULImmMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002047 return expandCondBranches(Inst, IDLoc, Instructions) ? MER_Fail
2048 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002049 case Mips::SDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002050 return expandDiv(Inst, IDLoc, Instructions, false, true) ? MER_Fail
2051 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002052 case Mips::DSDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002053 return expandDiv(Inst, IDLoc, Instructions, true, true) ? MER_Fail
2054 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002055 case Mips::UDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002056 return expandDiv(Inst, IDLoc, Instructions, false, false) ? MER_Fail
2057 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002058 case Mips::DUDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002059 return expandDiv(Inst, IDLoc, Instructions, true, false) ? MER_Fail
2060 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002061 case Mips::PseudoTRUNC_W_S:
2062 return expandTrunc(Inst, false, false, IDLoc, Instructions) ? MER_Fail
2063 : MER_Success;
2064 case Mips::PseudoTRUNC_W_D32:
2065 return expandTrunc(Inst, true, false, IDLoc, Instructions) ? MER_Fail
2066 : MER_Success;
2067 case Mips::PseudoTRUNC_W_D:
2068 return expandTrunc(Inst, true, true, IDLoc, Instructions) ? MER_Fail
2069 : MER_Success;
Daniel Sanders6394ee52015-10-15 14:52:58 +00002070 case Mips::Ulh:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002071 return expandUlh(Inst, true, IDLoc, Instructions) ? MER_Fail : MER_Success;
Toma Tabacud88d79c2015-06-23 14:39:42 +00002072 case Mips::Ulhu:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002073 return expandUlh(Inst, false, IDLoc, Instructions) ? MER_Fail : MER_Success;
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00002074 case Mips::Ulw:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002075 return expandUlw(Inst, IDLoc, Instructions) ? MER_Fail : MER_Success;
2076 case Mips::NORImm:
2077 return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail
2078 : MER_Success;
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002079 case Mips::ADDi:
2080 case Mips::ADDiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002081 case Mips::SLTi:
2082 case Mips::SLTiu:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002083 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2084 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2085 int64_t ImmValue = Inst.getOperand(2).getImm();
2086 if (isInt<16>(ImmValue))
2087 return MER_NotAMacro;
2088 return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail
2089 : MER_Success;
2090 }
2091 return MER_NotAMacro;
2092 case Mips::ANDi:
2093 case Mips::ORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002094 case Mips::XORi:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002095 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2096 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2097 int64_t ImmValue = Inst.getOperand(2).getImm();
2098 if (isUInt<16>(ImmValue))
2099 return MER_NotAMacro;
2100 return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail
2101 : MER_Success;
2102 }
2103 return MER_NotAMacro;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002104 case Mips::ROL:
2105 case Mips::ROR:
2106 return expandRotation(Inst, IDLoc, Instructions) ? MER_Fail
2107 : MER_Success;
2108 case Mips::ROLImm:
2109 case Mips::RORImm:
2110 return expandRotationImm(Inst, IDLoc, Instructions) ? MER_Fail
2111 : MER_Success;
2112 case Mips::DROL:
2113 case Mips::DROR:
2114 return expandDRotation(Inst, IDLoc, Instructions) ? MER_Fail
2115 : MER_Success;
2116 case Mips::DROLImm:
2117 case Mips::DRORImm:
2118 return expandDRotationImm(Inst, IDLoc, Instructions) ? MER_Fail
2119 : MER_Success;
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00002120 case Mips::ABSMacro:
2121 return expandAbs(Inst, IDLoc, Instructions) ? MER_Fail
2122 : MER_Success;
Jack Carterd0bd6422013-04-18 00:41:53 +00002123 }
Jack Carter30a59822012-10-04 04:03:53 +00002124}
Jack Carter92995f12012-10-06 00:53:28 +00002125
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002126bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
2127 SmallVectorImpl<MCInst> &Instructions) {
2128 // Create a JALR instruction which is going to replace the pseudo-JAL.
2129 MCInst JalrInst;
2130 JalrInst.setLoc(IDLoc);
2131 const MCOperand FirstRegOp = Inst.getOperand(0);
2132 const unsigned Opcode = Inst.getOpcode();
2133
2134 if (Opcode == Mips::JalOneReg) {
2135 // jal $rs => jalr $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002136 if (IsCpRestoreSet && inMicroMipsMode()) {
2137 JalrInst.setOpcode(Mips::JALRS16_MM);
2138 JalrInst.addOperand(FirstRegOp);
2139 } else if (inMicroMipsMode()) {
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002140 JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002141 JalrInst.addOperand(FirstRegOp);
2142 } else {
2143 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002144 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002145 JalrInst.addOperand(FirstRegOp);
2146 }
2147 } else if (Opcode == Mips::JalTwoReg) {
2148 // jal $rd, $rs => jalr $rd, $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002149 if (IsCpRestoreSet && inMicroMipsMode())
2150 JalrInst.setOpcode(Mips::JALRS_MM);
2151 else
2152 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002153 JalrInst.addOperand(FirstRegOp);
2154 const MCOperand SecondRegOp = Inst.getOperand(1);
2155 JalrInst.addOperand(SecondRegOp);
2156 }
2157 Instructions.push_back(JalrInst);
2158
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002159 // If .set reorder is active and branch instruction has a delay slot,
2160 // emit a NOP after it.
2161 const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
2162 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) {
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002163 createNop(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc, Instructions);
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002164 }
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002165
2166 return false;
2167}
2168
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002169/// Can the value be represented by a unsigned N-bit value and a shift left?
Benjamin Kramer039b1042015-10-28 13:54:36 +00002170template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002171 unsigned BitNum = findFirstSet(x);
2172
2173 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2174}
2175
2176/// Load (or add) an immediate into a register.
2177///
2178/// @param ImmValue The immediate to load.
2179/// @param DstReg The register that will hold the immediate.
2180/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2181/// for a simple initialization.
2182/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2183/// @param IsAddress True if the immediate represents an address. False if it
2184/// is an integer.
2185/// @param IDLoc Location of the immediate in the source file.
2186/// @param Instructions The instructions emitted by this expansion.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002187bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002188 unsigned SrcReg, bool Is32BitImm,
2189 bool IsAddress, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00002190 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu00e98672015-05-01 12:19:27 +00002191 if (!Is32BitImm && !isGP64bit()) {
2192 Error(IDLoc, "instruction requires a 64-bit architecture");
2193 return true;
2194 }
2195
Daniel Sanders03f9c012015-07-14 12:24:22 +00002196 if (Is32BitImm) {
2197 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2198 // Sign extend up to 64-bit so that the predicates match the hardware
2199 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2200 // true.
2201 ImmValue = SignExtend64<32>(ImmValue);
2202 } else {
2203 Error(IDLoc, "instruction requires a 32-bit immediate");
2204 return true;
2205 }
2206 }
2207
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002208 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2209 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2210
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002211 bool UseSrcReg = false;
2212 if (SrcReg != Mips::NoRegister)
2213 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002214
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002215 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002216 if (UseSrcReg &&
2217 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002218 // At this point we need AT to perform the expansions and we exit if it is
2219 // not available.
2220 unsigned ATReg = getATReg(IDLoc);
2221 if (!ATReg)
2222 return true;
2223 TmpReg = ATReg;
2224 }
2225
Daniel Sanders03f9c012015-07-14 12:24:22 +00002226 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002227 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002228 SrcReg = ZeroReg;
2229
2230 // This doesn't quite follow the usual ABI expectations for N32 but matches
2231 // traditional assembler behaviour. N32 would normally use addiu for both
2232 // integers and addresses.
2233 if (IsAddress && !Is32BitImm) {
2234 emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
2235 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002236 }
2237
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002238 emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
2239 return false;
2240 }
2241
2242 if (isUInt<16>(ImmValue)) {
2243 unsigned TmpReg = DstReg;
2244 if (SrcReg == DstReg) {
2245 TmpReg = getATReg(IDLoc);
2246 if (!TmpReg)
2247 return true;
2248 }
2249
2250 emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002251 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002252 emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2253 return false;
2254 }
2255
2256 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002257 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002258
Toma Tabacu79588102015-04-29 10:19:56 +00002259 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2260 uint16_t Bits15To0 = ImmValue & 0xffff;
2261
Toma Tabacua3d056f2015-05-15 09:42:11 +00002262 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002263 // Traditional behaviour seems to special case this particular value. It's
2264 // not clear why other masks are handled differently.
2265 if (ImmValue == 0xffffffff) {
Daniel Sandersf1ae3672015-08-18 09:55:57 +00002266 emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, Instructions);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002267 emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, Instructions);
2268 if (UseSrcReg)
2269 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2270 return false;
2271 }
2272
2273 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002274 // upper 32 bits.
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002275 emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002276 emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, Instructions);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002277 if (Bits15To0)
2278 emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
2279 if (UseSrcReg)
2280 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2281 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002282 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002283
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002284 emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, Instructions);
2285 if (Bits15To0)
2286 emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002287 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002288 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2289 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002290 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002291
2292 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2293 if (Is32BitImm) {
2294 Error(IDLoc, "instruction requires a 32-bit immediate");
2295 return true;
2296 }
2297
2298 // Traditionally, these immediates are shifted as little as possible and as
2299 // such we align the most significant bit to bit 15 of our temporary.
2300 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2301 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2302 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2303 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
2304 emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, Instructions);
2305 emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, Instructions);
2306
2307 if (UseSrcReg)
2308 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2309
2310 return false;
2311 }
2312
2313 warnIfNoMacro(IDLoc);
2314
2315 // The remaining case is packed with a sequence of dsll and ori with zeros
2316 // being omitted and any neighbouring dsll's being coalesced.
2317 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2318
2319 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2320 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
2321 IDLoc, Instructions))
2322 return false;
2323
2324 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2325 // skip it and defer the shift to the next chunk.
2326 unsigned ShiftCarriedForwards = 16;
2327 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2328 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2329
2330 if (ImmChunk != 0) {
2331 emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
2332 Instructions);
2333 emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, Instructions);
2334 ShiftCarriedForwards = 0;
2335 }
2336
2337 ShiftCarriedForwards += 16;
2338 }
2339 ShiftCarriedForwards -= 16;
2340
2341 // Finish any remaining shifts left by trailing zeros.
2342 if (ShiftCarriedForwards)
2343 emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
2344 Instructions);
2345
2346 if (UseSrcReg)
2347 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2348
Matheus Almeida3813d572014-06-19 14:39:14 +00002349 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002350}
Jack Carter92995f12012-10-06 00:53:28 +00002351
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002352bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
2353 SmallVectorImpl<MCInst> &Instructions) {
2354 const MCOperand &ImmOp = Inst.getOperand(1);
2355 assert(ImmOp.isImm() && "expected immediate operand kind");
2356 const MCOperand &DstRegOp = Inst.getOperand(0);
2357 assert(DstRegOp.isReg() && "expected register operand kind");
2358
2359 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002360 Is32BitImm, false, IDLoc, Instructions))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002361 return true;
2362
2363 return false;
2364}
2365
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002366bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2367 const MCOperand &Offset,
2368 bool Is32BitAddress, SMLoc IDLoc,
2369 SmallVectorImpl<MCInst> &Instructions) {
2370 // la can't produce a usable address when addresses are 64-bit.
2371 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2372 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2373 // We currently can't do this because we depend on the equality
2374 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2375 Error(IDLoc, "la used to load 64-bit address");
2376 // Continue as if we had 'dla' instead.
2377 Is32BitAddress = false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002378 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002379
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002380 // dla requires 64-bit addresses.
Scott Egerton24557012016-01-21 15:11:01 +00002381 if (!Is32BitAddress && !hasMips3()) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002382 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002383 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002384 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002385
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002386 if (!Offset.isImm())
2387 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
2388 Is32BitAddress, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002389
Scott Egerton24557012016-01-21 15:11:01 +00002390 if (!ABI.ArePtrs64bit()) {
2391 // Continue as if we had 'la' whether we had 'la' or 'dla'.
2392 Is32BitAddress = true;
2393 }
2394
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002395 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
2396 IDLoc, Instructions);
Jack Carter543fdf82012-10-09 23:29:45 +00002397}
2398
Toma Tabacuf712ede2015-06-17 14:31:51 +00002399bool MipsAsmParser::loadAndAddSymbolAddress(
2400 const MCExpr *SymExpr, unsigned DstReg, unsigned SrcReg, bool Is32BitSym,
2401 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002402 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002403
Daniel Sandersd5a89412015-10-05 13:19:29 +00002404 const MCExpr *Symbol = cast<MCExpr>(SymExpr);
2405 const MipsMCExpr *HiExpr = MipsMCExpr::create(
2406 MCSymbolRefExpr::VK_Mips_ABS_HI, Symbol, getContext());
2407 const MipsMCExpr *LoExpr = MipsMCExpr::create(
2408 MCSymbolRefExpr::VK_Mips_ABS_LO, Symbol, getContext());
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002409
Toma Tabacufb9d1252015-06-22 12:08:39 +00002410 bool UseSrcReg = SrcReg != Mips::NoRegister;
2411
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002412 // This is the 64-bit symbol address expansion.
2413 if (ABI.ArePtrs64bit() && isGP64bit()) {
2414 // We always need AT for the 64-bit expansion.
2415 // If it is not available we exit.
2416 unsigned ATReg = getATReg(IDLoc);
2417 if (!ATReg)
2418 return true;
2419
Daniel Sandersd5a89412015-10-05 13:19:29 +00002420 const MipsMCExpr *HighestExpr = MipsMCExpr::create(
2421 MCSymbolRefExpr::VK_Mips_HIGHEST, Symbol, getContext());
2422 const MipsMCExpr *HigherExpr = MipsMCExpr::create(
2423 MCSymbolRefExpr::VK_Mips_HIGHER, Symbol, getContext());
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002424
Scott Egerton24557012016-01-21 15:11:01 +00002425 if (UseSrcReg &&
2426 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2427 SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002428 // If $rs is the same as $rd:
2429 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
2430 // daddiu $at, $at, %higher(sym)
2431 // dsll $at, $at, 16
2432 // daddiu $at, $at, %hi(sym)
2433 // dsll $at, $at, 16
2434 // daddiu $at, $at, %lo(sym)
2435 // daddu $rd, $at, $rd
2436 emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
2437 Instructions);
2438 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HigherExpr),
2439 IDLoc, Instructions);
2440 emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
2441 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
2442 Instructions);
2443 emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
2444 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
2445 Instructions);
2446 emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, Instructions);
2447
2448 return false;
2449 }
2450
2451 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2452 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
2453 // lui $at, %hi(sym)
2454 // daddiu $rd, $rd, %higher(sym)
2455 // daddiu $at, $at, %lo(sym)
2456 // dsll32 $rd, $rd, 0
2457 // daddu $rd, $rd, $at
2458 // (daddu $rd, $rd, $rs)
2459 emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
2460 Instructions);
2461 emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
2462 Instructions);
2463 emitRRX(Mips::DADDiu, DstReg, DstReg, MCOperand::createExpr(HigherExpr),
2464 IDLoc, Instructions);
2465 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
2466 Instructions);
2467 emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, Instructions);
2468 emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, Instructions);
2469 if (UseSrcReg)
2470 emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, Instructions);
2471
2472 return false;
2473 }
2474
2475 // And now, the 32-bit symbol address expansion:
2476 // If $rs is the same as $rd:
2477 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
2478 // ori $at, $at, %lo(sym)
2479 // addu $rd, $at, $rd
2480 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2481 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
2482 // ori $rd, $rd, %lo(sym)
2483 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00002484 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002485 if (UseSrcReg &&
2486 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002487 // If $rs is the same as $rd, we need to use AT.
2488 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00002489 unsigned ATReg = getATReg(IDLoc);
2490 if (!ATReg)
2491 return true;
2492 TmpReg = ATReg;
2493 }
2494
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002495 emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, Instructions);
2496 emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr), IDLoc,
2497 Instructions);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002498
Toma Tabacufb9d1252015-06-22 12:08:39 +00002499 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002500 emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2501 else
Scott Egerton24557012016-01-21 15:11:01 +00002502 assert(
2503 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, TmpReg));
Toma Tabacuf712ede2015-06-17 14:31:51 +00002504
Toma Tabacu674825c2015-06-16 12:16:24 +00002505 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002506}
2507
NAKAMURA Takumi2bbc90c2015-01-23 01:02:07 +00002508bool MipsAsmParser::expandUncondBranchMMPseudo(
2509 MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00002510 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
2511 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002512
2513 MCOperand Offset = Inst.getOperand(0);
2514 if (Offset.isExpr()) {
2515 Inst.clear();
2516 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002517 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2518 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2519 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002520 } else {
2521 assert(Offset.isImm() && "expected immediate operand kind");
Craig Topper55b1f292015-10-10 20:17:07 +00002522 if (isInt<11>(Offset.getImm())) {
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002523 // If offset fits into 11 bits then this instruction becomes microMIPS
2524 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00002525 if (inMicroMipsMode())
2526 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002527 } else {
Craig Topper55b1f292015-10-10 20:17:07 +00002528 if (!isInt<17>(Offset.getImm()))
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002529 Error(IDLoc, "branch target out of range");
2530 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
2531 Error(IDLoc, "branch to misaligned address");
2532 Inst.clear();
2533 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002534 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2535 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2536 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002537 }
2538 }
2539 Instructions.push_back(Inst);
2540
Zoran Jovanovicada70912015-09-07 11:56:37 +00002541 // If .set reorder is active and branch instruction has a delay slot,
2542 // emit a NOP after it.
2543 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
2544 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Toma Tabacu234482a2015-03-16 12:03:39 +00002545 createNop(true, IDLoc, Instructions);
2546
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002547 return false;
2548}
2549
Toma Tabacue1e460d2015-06-11 10:36:10 +00002550bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc,
2551 SmallVectorImpl<MCInst> &Instructions) {
2552 const MCOperand &DstRegOp = Inst.getOperand(0);
2553 assert(DstRegOp.isReg() && "expected register operand kind");
2554
2555 const MCOperand &ImmOp = Inst.getOperand(1);
2556 assert(ImmOp.isImm() && "expected immediate operand kind");
2557
2558 const MCOperand &MemOffsetOp = Inst.getOperand(2);
Daniel Sanders90f0d0b2016-02-29 11:24:49 +00002559 assert((MemOffsetOp.isImm() || MemOffsetOp.isExpr()) &&
2560 "expected immediate or expression operand");
Toma Tabacue1e460d2015-06-11 10:36:10 +00002561
2562 unsigned OpCode = 0;
2563 switch(Inst.getOpcode()) {
2564 case Mips::BneImm:
2565 OpCode = Mips::BNE;
2566 break;
2567 case Mips::BeqImm:
2568 OpCode = Mips::BEQ;
2569 break;
2570 default:
2571 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
2572 break;
2573 }
2574
2575 int64_t ImmValue = ImmOp.getImm();
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002576 if (ImmValue == 0)
2577 emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
2578 Instructions);
2579 else {
Toma Tabacue1e460d2015-06-11 10:36:10 +00002580 warnIfNoMacro(IDLoc);
2581
2582 unsigned ATReg = getATReg(IDLoc);
2583 if (!ATReg)
2584 return true;
2585
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002586 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
2587 IDLoc, Instructions))
Toma Tabacue1e460d2015-06-11 10:36:10 +00002588 return true;
2589
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002590 emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, Instructions);
Toma Tabacue1e460d2015-06-11 10:36:10 +00002591 }
2592 return false;
2593}
2594
Jack Carter9e65aa32013-03-22 00:05:30 +00002595void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00002596 SmallVectorImpl<MCInst> &Instructions,
2597 bool isLoad, bool isImmOpnd) {
Scott Egertond65377d2016-03-17 10:37:51 +00002598 MCOperand HiOperand, LoOperand;
Jack Carter9e65aa32013-03-22 00:05:30 +00002599 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00002600 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002601 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2602 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002603 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002604 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2605 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002606 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00002607 if (isImmOpnd) {
2608 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
Scott Egertond65377d2016-03-17 10:37:51 +00002609 unsigned ImmOffset = Inst.getOperand(2).getImm();
2610 unsigned LoOffset = ImmOffset & 0x0000ffff;
2611 unsigned HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00002612 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00002613 if (LoOffset & 0x8000)
2614 HiOffset++;
Scott Egertond65377d2016-03-17 10:37:51 +00002615 LoOperand = MCOperand::createImm(LoOffset);
2616 HiOperand = MCOperand::createImm(HiOffset);
2617 } else {
2618 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
2619 LoOperand = MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "lo"));
2620 HiOperand = MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "hi"));
2621 }
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002622 // These are some of the types of expansions we perform here:
2623 // 1) lw $8, sym => lui $8, %hi(sym)
2624 // lw $8, %lo(sym)($8)
2625 // 2) lw $8, offset($9) => lui $8, %hi(offset)
2626 // add $8, $8, $9
2627 // lw $8, %lo(offset)($9)
2628 // 3) lw $8, offset($8) => lui $at, %hi(offset)
2629 // add $at, $at, $8
2630 // lw $8, %lo(offset)($at)
2631 // 4) sw $8, sym => lui $at, %hi(sym)
2632 // sw $8, %lo(sym)($at)
2633 // 5) sw $8, offset($8) => lui $at, %hi(offset)
2634 // add $at, $at, $8
2635 // sw $8, %lo(offset)($at)
2636 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
2637 // ldc1 $f0, %lo(sym)($at)
2638 //
2639 // For load instructions we can use the destination register as a temporary
2640 // if base and dst are different (examples 1 and 2) and if the base register
2641 // is general purpose otherwise we must use $at (example 6) and error if it's
2642 // not available. For stores we must use $at (examples 4 and 5) because we
2643 // must not clobber the source register setting up the offset.
2644 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
2645 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
2646 unsigned RegClassIDOp0 =
2647 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
2648 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
2649 (RegClassIDOp0 == Mips::GPR64RegClassID);
2650 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00002651 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002652 else {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002653 // At this point we need AT to perform the expansions and we exit if it is
2654 // not available.
Toma Tabacu89a712b2015-04-15 10:48:56 +00002655 TmpRegNum = getATReg(IDLoc);
2656 if (!TmpRegNum)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002657 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002658 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002659
Scott Egertond65377d2016-03-17 10:37:51 +00002660 emitRX(Mips::LUi, TmpRegNum, HiOperand, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00002661 // Add temp register to base.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002662 if (BaseRegNum != Mips::ZERO)
2663 emitRRR(Mips::ADDu, TmpRegNum, TmpRegNum, BaseRegNum, IDLoc, Instructions);
Alp Tokercb402912014-01-24 17:20:08 +00002664 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00002665 // of offset and new base.
Scott Egertond65377d2016-03-17 10:37:51 +00002666 emitRRX(Inst.getOpcode(), RegOpNum, TmpRegNum, LoOperand, IDLoc, Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +00002667}
2668
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002669bool
2670MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2671 SmallVectorImpl<MCInst> &Instructions) {
2672 unsigned OpNum = Inst.getNumOperands();
2673 unsigned Opcode = Inst.getOpcode();
2674 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2675
2676 assert (Inst.getOperand(OpNum - 1).isImm() &&
2677 Inst.getOperand(OpNum - 2).isReg() &&
2678 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2679
2680 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2681 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002682 (Inst.getOperand(OpNum - 2).getReg() == Mips::SP ||
2683 Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) &&
2684 (Inst.getOperand(OpNum - 3).getReg() == Mips::RA ||
2685 Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002686 // It can be implemented as SWM16 or LWM16 instruction.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002687 if (inMicroMipsMode() && hasMips32r6())
2688 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6;
2689 else
2690 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2691 }
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002692
2693 Inst.setOpcode(NewOpcode);
2694 Instructions.push_back(Inst);
2695 return false;
2696}
2697
Toma Tabacu1a108322015-06-17 13:20:24 +00002698bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
2699 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002700 bool EmittedNoMacroWarning = false;
Toma Tabacu1a108322015-06-17 13:20:24 +00002701 unsigned PseudoOpcode = Inst.getOpcode();
2702 unsigned SrcReg = Inst.getOperand(0).getReg();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002703 const MCOperand &TrgOp = Inst.getOperand(1);
Toma Tabacu1a108322015-06-17 13:20:24 +00002704 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
2705
2706 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002707 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00002708
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002709 unsigned TrgReg;
2710 if (TrgOp.isReg())
2711 TrgReg = TrgOp.getReg();
2712 else if (TrgOp.isImm()) {
2713 warnIfNoMacro(IDLoc);
2714 EmittedNoMacroWarning = true;
2715
2716 TrgReg = getATReg(IDLoc);
2717 if (!TrgReg)
2718 return true;
2719
2720 switch(PseudoOpcode) {
2721 default:
2722 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2723 case Mips::BLTImmMacro:
2724 PseudoOpcode = Mips::BLT;
2725 break;
2726 case Mips::BLEImmMacro:
2727 PseudoOpcode = Mips::BLE;
2728 break;
2729 case Mips::BGEImmMacro:
2730 PseudoOpcode = Mips::BGE;
2731 break;
2732 case Mips::BGTImmMacro:
2733 PseudoOpcode = Mips::BGT;
2734 break;
2735 case Mips::BLTUImmMacro:
2736 PseudoOpcode = Mips::BLTU;
2737 break;
2738 case Mips::BLEUImmMacro:
2739 PseudoOpcode = Mips::BLEU;
2740 break;
2741 case Mips::BGEUImmMacro:
2742 PseudoOpcode = Mips::BGEU;
2743 break;
2744 case Mips::BGTUImmMacro:
2745 PseudoOpcode = Mips::BGTU;
2746 break;
2747 case Mips::BLTLImmMacro:
2748 PseudoOpcode = Mips::BLTL;
2749 break;
2750 case Mips::BLELImmMacro:
2751 PseudoOpcode = Mips::BLEL;
2752 break;
2753 case Mips::BGELImmMacro:
2754 PseudoOpcode = Mips::BGEL;
2755 break;
2756 case Mips::BGTLImmMacro:
2757 PseudoOpcode = Mips::BGTL;
2758 break;
2759 case Mips::BLTULImmMacro:
2760 PseudoOpcode = Mips::BLTUL;
2761 break;
2762 case Mips::BLEULImmMacro:
2763 PseudoOpcode = Mips::BLEUL;
2764 break;
2765 case Mips::BGEULImmMacro:
2766 PseudoOpcode = Mips::BGEUL;
2767 break;
2768 case Mips::BGTULImmMacro:
2769 PseudoOpcode = Mips::BGTUL;
2770 break;
2771 }
2772
2773 if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
2774 false, IDLoc, Instructions))
2775 return true;
2776 }
2777
Toma Tabacu1a108322015-06-17 13:20:24 +00002778 switch (PseudoOpcode) {
2779 case Mips::BLT:
2780 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002781 case Mips::BLTL:
2782 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002783 AcceptsEquality = false;
2784 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002785 IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
2786 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002787 ZeroSrcOpcode = Mips::BGTZ;
2788 ZeroTrgOpcode = Mips::BLTZ;
2789 break;
2790 case Mips::BLE:
2791 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002792 case Mips::BLEL:
2793 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002794 AcceptsEquality = true;
2795 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002796 IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
2797 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002798 ZeroSrcOpcode = Mips::BGEZ;
2799 ZeroTrgOpcode = Mips::BLEZ;
2800 break;
2801 case Mips::BGE:
2802 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002803 case Mips::BGEL:
2804 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002805 AcceptsEquality = true;
2806 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002807 IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
2808 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002809 ZeroSrcOpcode = Mips::BLEZ;
2810 ZeroTrgOpcode = Mips::BGEZ;
2811 break;
2812 case Mips::BGT:
2813 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002814 case Mips::BGTL:
2815 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002816 AcceptsEquality = false;
2817 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002818 IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
2819 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002820 ZeroSrcOpcode = Mips::BLTZ;
2821 ZeroTrgOpcode = Mips::BGTZ;
2822 break;
2823 default:
2824 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2825 }
2826
Toma Tabacu1a108322015-06-17 13:20:24 +00002827 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
2828 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
2829 if (IsSrcRegZero && IsTrgRegZero) {
2830 // FIXME: All of these Opcode-specific if's are needed for compatibility
2831 // with GAS' behaviour. However, they may not generate the most efficient
2832 // code in some circumstances.
2833 if (PseudoOpcode == Mips::BLT) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002834 emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2835 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002836 return false;
2837 }
2838 if (PseudoOpcode == Mips::BLE) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002839 emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2840 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002841 Warning(IDLoc, "branch is always taken");
2842 return false;
2843 }
2844 if (PseudoOpcode == Mips::BGE) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002845 emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2846 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002847 Warning(IDLoc, "branch is always taken");
2848 return false;
2849 }
2850 if (PseudoOpcode == Mips::BGT) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002851 emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2852 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002853 return false;
2854 }
2855 if (PseudoOpcode == Mips::BGTU) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002856 emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
2857 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002858 return false;
2859 }
2860 if (AcceptsEquality) {
2861 // If both registers are $0 and the pseudo-branch accepts equality, it
2862 // will always be taken, so we emit an unconditional branch.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002863 emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
2864 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002865 Warning(IDLoc, "branch is always taken");
2866 return false;
2867 }
2868 // If both registers are $0 and the pseudo-branch does not accept
2869 // equality, it will never be taken, so we don't have to emit anything.
2870 return false;
2871 }
2872 if (IsSrcRegZero || IsTrgRegZero) {
2873 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
2874 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
2875 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
2876 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
2877 // the pseudo-branch will never be taken, so we don't emit anything.
2878 // This only applies to unsigned pseudo-branches.
2879 return false;
2880 }
2881 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
2882 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
2883 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
2884 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
2885 // the pseudo-branch will always be taken, so we emit an unconditional
2886 // branch.
2887 // This only applies to unsigned pseudo-branches.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002888 emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
2889 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002890 Warning(IDLoc, "branch is always taken");
2891 return false;
2892 }
2893 if (IsUnsigned) {
2894 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
2895 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
2896 // the pseudo-branch will be taken only when the non-zero register is
2897 // different from 0, so we emit a BNEZ.
2898 //
2899 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
2900 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
2901 // the pseudo-branch will be taken only when the non-zero register is
2902 // equal to 0, so we emit a BEQZ.
2903 //
2904 // Because only BLEU and BGEU branch on equality, we can use the
2905 // AcceptsEquality variable to decide when to emit the BEQZ.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002906 emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
2907 IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
2908 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002909 return false;
2910 }
2911 // If we have a signed pseudo-branch and one of the registers is $0,
2912 // we can use an appropriate compare-to-zero branch. We select which one
2913 // to use in the switch statement above.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002914 emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
2915 IsSrcRegZero ? TrgReg : SrcReg, MCOperand::createExpr(OffsetExpr),
2916 IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002917 return false;
2918 }
2919
2920 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
2921 // expansions. If it is not available, we return.
2922 unsigned ATRegNum = getATReg(IDLoc);
2923 if (!ATRegNum)
2924 return true;
2925
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002926 if (!EmittedNoMacroWarning)
2927 warnIfNoMacro(IDLoc);
Toma Tabacu1a108322015-06-17 13:20:24 +00002928
2929 // SLT fits well with 2 of our 4 pseudo-branches:
2930 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
2931 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
2932 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
2933 // This is accomplished by using a BNEZ with the result of the SLT.
2934 //
2935 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
2936 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
2937 // Because only BGE and BLE branch on equality, we can use the
2938 // AcceptsEquality variable to decide when to emit the BEQZ.
2939 // Note that the order of the SLT arguments doesn't change between
2940 // opposites.
2941 //
2942 // The same applies to the unsigned variants, except that SLTu is used
2943 // instead of SLT.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002944 emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
2945 ReverseOrderSLT ? TrgReg : SrcReg, ReverseOrderSLT ? SrcReg : TrgReg,
2946 IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002947
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002948 emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
2949 : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
2950 ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2951 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002952 return false;
2953}
2954
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002955bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc,
2956 SmallVectorImpl<MCInst> &Instructions,
2957 const bool IsMips64, const bool Signed) {
2958 if (hasMips32r6()) {
2959 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
2960 return false;
2961 }
2962
2963 warnIfNoMacro(IDLoc);
2964
2965 const MCOperand &RsRegOp = Inst.getOperand(0);
2966 assert(RsRegOp.isReg() && "expected register operand kind");
2967 unsigned RsReg = RsRegOp.getReg();
2968
2969 const MCOperand &RtRegOp = Inst.getOperand(1);
2970 assert(RtRegOp.isReg() && "expected register operand kind");
2971 unsigned RtReg = RtRegOp.getReg();
2972 unsigned DivOp;
2973 unsigned ZeroReg;
2974
2975 if (IsMips64) {
2976 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
2977 ZeroReg = Mips::ZERO_64;
2978 } else {
2979 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
2980 ZeroReg = Mips::ZERO;
2981 }
2982
2983 bool UseTraps = useTraps();
2984
2985 if (RsReg == Mips::ZERO || RsReg == Mips::ZERO_64) {
2986 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)
2987 Warning(IDLoc, "dividing zero by zero");
2988 if (IsMips64) {
2989 if (Signed && (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)) {
2990 if (UseTraps) {
2991 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2992 return false;
2993 }
2994
2995 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2996 return false;
2997 }
2998 } else {
2999 emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
3000 return false;
3001 }
3002 }
3003
3004 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
3005 Warning(IDLoc, "division by zero");
3006 if (Signed) {
3007 if (UseTraps) {
3008 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
3009 return false;
3010 }
3011
3012 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
3013 return false;
3014 }
3015 }
3016
3017 // FIXME: The values for these two BranchTarget variables may be different in
3018 // micromips. These magic numbers need to be removed.
3019 unsigned BranchTargetNoTraps;
3020 unsigned BranchTarget;
3021
3022 if (UseTraps) {
3023 BranchTarget = IsMips64 ? 12 : 8;
3024 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
3025 } else {
3026 BranchTarget = IsMips64 ? 20 : 16;
3027 BranchTargetNoTraps = 8;
3028 // Branch to the li instruction.
3029 emitRRI(Mips::BNE, RtReg, ZeroReg, BranchTargetNoTraps, IDLoc,
3030 Instructions);
3031 }
3032
3033 emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
3034
3035 if (!UseTraps)
3036 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
3037
3038 if (!Signed) {
3039 emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
3040 return false;
3041 }
3042
3043 unsigned ATReg = getATReg(IDLoc);
3044 if (!ATReg)
3045 return true;
3046
3047 emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, Instructions);
3048 if (IsMips64) {
3049 // Branch to the mflo instruction.
3050 emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
3051 emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, Instructions);
3052 emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, Instructions);
3053 } else {
3054 // Branch to the mflo instruction.
3055 emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
3056 emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, Instructions);
3057 }
3058
3059 if (UseTraps)
3060 emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, Instructions);
3061 else {
3062 // Branch to the mflo instruction.
3063 emitRRI(Mips::BNE, RsReg, ATReg, BranchTargetNoTraps, IDLoc, Instructions);
3064 emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, Instructions);
3065 emitII(Mips::BREAK, 0x6, 0, IDLoc, Instructions);
3066 }
3067 emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
3068 return false;
3069}
3070
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003071bool MipsAsmParser::expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU,
3072 SMLoc IDLoc,
3073 SmallVectorImpl<MCInst> &Instructions) {
3074
3075 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
3076 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() &&
3077 Inst.getOperand(2).isReg() && "Invalid instruction operand.");
3078
3079 unsigned FirstReg = Inst.getOperand(0).getReg();
3080 unsigned SecondReg = Inst.getOperand(1).getReg();
3081 unsigned ThirdReg = Inst.getOperand(2).getReg();
3082
3083 if (hasMips1() && !hasMips2()) {
3084 unsigned ATReg = getATReg(IDLoc);
3085 if (!ATReg)
3086 return true;
3087 emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, Instructions);
3088 emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, Instructions);
3089 createNop(false, IDLoc, Instructions);
3090 emitRRI(Mips::ORi, ATReg, ThirdReg, 0x3, IDLoc, Instructions);
3091 emitRRI(Mips::XORi, ATReg, ATReg, 0x2, IDLoc, Instructions);
3092 emitRR(Mips::CTC1, Mips::RA, ATReg, IDLoc, Instructions);
3093 createNop(false, IDLoc, Instructions);
3094 emitRR(IsDouble ? (Is64FPU ? Mips::CVT_W_D64 : Mips::CVT_W_D32)
3095 : Mips::CVT_W_S,
3096 FirstReg, SecondReg, IDLoc, Instructions);
3097 emitRR(Mips::CTC1, Mips::RA, ThirdReg, IDLoc, Instructions);
3098 createNop(false, IDLoc, Instructions);
3099 return false;
3100 }
3101
3102 emitRR(IsDouble ? (Is64FPU ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32)
3103 : Mips::TRUNC_W_S,
3104 FirstReg, SecondReg, IDLoc, Instructions);
3105
3106 return false;
3107}
3108
Daniel Sanders6394ee52015-10-15 14:52:58 +00003109bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
3110 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacud88d79c2015-06-23 14:39:42 +00003111 if (hasMips32r6() || hasMips64r6()) {
3112 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3113 return false;
3114 }
3115
3116 warnIfNoMacro(IDLoc);
3117
3118 const MCOperand &DstRegOp = Inst.getOperand(0);
3119 assert(DstRegOp.isReg() && "expected register operand kind");
3120
3121 const MCOperand &SrcRegOp = Inst.getOperand(1);
3122 assert(SrcRegOp.isReg() && "expected register operand kind");
3123
3124 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3125 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3126
3127 unsigned DstReg = DstRegOp.getReg();
3128 unsigned SrcReg = SrcRegOp.getReg();
3129 int64_t OffsetValue = OffsetImmOp.getImm();
3130
3131 // NOTE: We always need AT for ULHU, as it is always used as the source
3132 // register for one of the LBu's.
3133 unsigned ATReg = getATReg(IDLoc);
3134 if (!ATReg)
3135 return true;
3136
3137 // When the value of offset+1 does not fit in 16 bits, we have to load the
3138 // offset in AT, (D)ADDu the original source register (if there was one), and
3139 // then use AT as the source register for the 2 generated LBu's.
3140 bool LoadedOffsetInAT = false;
3141 if (!isInt<16>(OffsetValue + 1) || !isInt<16>(OffsetValue)) {
3142 LoadedOffsetInAT = true;
3143
3144 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003145 true, IDLoc, Instructions))
Toma Tabacud88d79c2015-06-23 14:39:42 +00003146 return true;
3147
3148 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3149 // because it will make our output more similar to GAS'. For example,
3150 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3151 // instead of just an "ori $1, $9, 32768".
3152 // NOTE: If there is no source register specified in the ULHU, the parser
3153 // will interpret it as $0.
3154 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
3155 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
3156 }
3157
3158 unsigned FirstLbuDstReg = LoadedOffsetInAT ? DstReg : ATReg;
3159 unsigned SecondLbuDstReg = LoadedOffsetInAT ? ATReg : DstReg;
3160 unsigned LbuSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3161
3162 int64_t FirstLbuOffset = 0, SecondLbuOffset = 0;
3163 if (isLittle()) {
3164 FirstLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3165 SecondLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3166 } else {
3167 FirstLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3168 SecondLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3169 }
3170
3171 unsigned SllReg = LoadedOffsetInAT ? DstReg : ATReg;
3172
Daniel Sanders6394ee52015-10-15 14:52:58 +00003173 emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
3174 FirstLbuOffset, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003175
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003176 emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondLbuOffset, IDLoc,
3177 Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003178
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003179 emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003180
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003181 emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003182
3183 return false;
3184}
3185
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003186bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc,
3187 SmallVectorImpl<MCInst> &Instructions) {
3188 if (hasMips32r6() || hasMips64r6()) {
3189 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3190 return false;
3191 }
3192
3193 const MCOperand &DstRegOp = Inst.getOperand(0);
3194 assert(DstRegOp.isReg() && "expected register operand kind");
3195
3196 const MCOperand &SrcRegOp = Inst.getOperand(1);
3197 assert(SrcRegOp.isReg() && "expected register operand kind");
3198
3199 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3200 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3201
3202 unsigned SrcReg = SrcRegOp.getReg();
3203 int64_t OffsetValue = OffsetImmOp.getImm();
3204 unsigned ATReg = 0;
3205
3206 // When the value of offset+3 does not fit in 16 bits, we have to load the
3207 // offset in AT, (D)ADDu the original source register (if there was one), and
3208 // then use AT as the source register for the generated LWL and LWR.
3209 bool LoadedOffsetInAT = false;
3210 if (!isInt<16>(OffsetValue + 3) || !isInt<16>(OffsetValue)) {
3211 ATReg = getATReg(IDLoc);
3212 if (!ATReg)
3213 return true;
3214 LoadedOffsetInAT = true;
3215
3216 warnIfNoMacro(IDLoc);
3217
3218 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003219 true, IDLoc, Instructions))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003220 return true;
3221
3222 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3223 // because it will make our output more similar to GAS'. For example,
3224 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3225 // instead of just an "ori $1, $9, 32768".
3226 // NOTE: If there is no source register specified in the ULW, the parser
3227 // will interpret it as $0.
3228 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
3229 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
3230 }
3231
3232 unsigned FinalSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3233 int64_t LeftLoadOffset = 0, RightLoadOffset = 0;
3234 if (isLittle()) {
3235 LeftLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3236 RightLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3237 } else {
3238 LeftLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3239 RightLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3240 }
3241
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003242 emitRRI(Mips::LWL, DstRegOp.getReg(), FinalSrcReg, LeftLoadOffset, IDLoc,
3243 Instructions);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003244
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003245 emitRRI(Mips::LWR, DstRegOp.getReg(), FinalSrcReg, RightLoadOffset, IDLoc,
3246 Instructions);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003247
3248 return false;
3249}
3250
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003251bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
3252 SmallVectorImpl<MCInst> &Instructions) {
3253
3254 assert (Inst.getNumOperands() == 3 && "Invalid operand count");
3255 assert (Inst.getOperand(0).isReg() &&
3256 Inst.getOperand(1).isReg() &&
3257 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
3258
3259 unsigned ATReg = Mips::NoRegister;
3260 unsigned FinalDstReg = Mips::NoRegister;
3261 unsigned DstReg = Inst.getOperand(0).getReg();
3262 unsigned SrcReg = Inst.getOperand(1).getReg();
3263 int64_t ImmValue = Inst.getOperand(2).getImm();
3264
3265 bool Is32Bit = isInt<32>(ImmValue) || isUInt<32>(ImmValue);
3266
3267 unsigned FinalOpcode = Inst.getOpcode();
3268
3269 if (DstReg == SrcReg) {
3270 ATReg = getATReg(Inst.getLoc());
3271 if (!ATReg)
3272 return true;
3273 FinalDstReg = DstReg;
3274 DstReg = ATReg;
3275 }
3276
3277 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Instructions)) {
3278 switch (FinalOpcode) {
3279 default:
3280 llvm_unreachable("unimplemented expansion");
3281 case (Mips::ADDi):
3282 FinalOpcode = Mips::ADD;
3283 break;
3284 case (Mips::ADDiu):
3285 FinalOpcode = Mips::ADDu;
3286 break;
3287 case (Mips::ANDi):
3288 FinalOpcode = Mips::AND;
3289 break;
3290 case (Mips::NORImm):
3291 FinalOpcode = Mips::NOR;
3292 break;
3293 case (Mips::ORi):
3294 FinalOpcode = Mips::OR;
3295 break;
3296 case (Mips::SLTi):
3297 FinalOpcode = Mips::SLT;
3298 break;
3299 case (Mips::SLTiu):
3300 FinalOpcode = Mips::SLTu;
3301 break;
3302 case (Mips::XORi):
3303 FinalOpcode = Mips::XOR;
3304 break;
3305 }
3306
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003307 if (FinalDstReg == Mips::NoRegister)
3308 emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, Instructions);
3309 else
3310 emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc,
3311 Instructions);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003312 return false;
3313 }
3314 return true;
3315}
3316
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003317bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc,
3318 SmallVectorImpl<MCInst> &Instructions) {
3319 unsigned ATReg = Mips::NoRegister;
3320 unsigned DReg = Inst.getOperand(0).getReg();
3321 unsigned SReg = Inst.getOperand(1).getReg();
3322 unsigned TReg = Inst.getOperand(2).getReg();
3323 unsigned TmpReg = DReg;
3324
3325 unsigned FirstShift = Mips::NOP;
3326 unsigned SecondShift = Mips::NOP;
3327
3328 if (hasMips32r2()) {
3329
3330 if (DReg == SReg) {
3331 TmpReg = getATReg(Inst.getLoc());
3332 if (!TmpReg)
3333 return true;
3334 }
3335
3336 if (Inst.getOpcode() == Mips::ROL) {
3337 emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions);
3338 emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), Instructions);
3339 return false;
3340 }
3341
3342 if (Inst.getOpcode() == Mips::ROR) {
3343 emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), Instructions);
3344 return false;
3345 }
3346
3347 return true;
3348 }
3349
3350 if (hasMips32()) {
3351
3352 switch (Inst.getOpcode()) {
3353 default:
3354 llvm_unreachable("unexpected instruction opcode");
3355 case Mips::ROL:
3356 FirstShift = Mips::SRLV;
3357 SecondShift = Mips::SLLV;
3358 break;
3359 case Mips::ROR:
3360 FirstShift = Mips::SLLV;
3361 SecondShift = Mips::SRLV;
3362 break;
3363 }
3364
3365 ATReg = getATReg(Inst.getLoc());
3366 if (!ATReg)
3367 return true;
3368
3369 emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions);
3370 emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), Instructions);
3371 emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), Instructions);
3372 emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions);
3373
3374 return false;
3375 }
3376
3377 return true;
3378}
3379
3380bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
3381 SmallVectorImpl<MCInst> &Instructions) {
3382
3383 unsigned ATReg = Mips::NoRegister;
3384 unsigned DReg = Inst.getOperand(0).getReg();
3385 unsigned SReg = Inst.getOperand(1).getReg();
3386 int64_t ImmValue = Inst.getOperand(2).getImm();
3387
3388 unsigned FirstShift = Mips::NOP;
3389 unsigned SecondShift = Mips::NOP;
3390
3391 if (hasMips32r2()) {
3392
3393 if (Inst.getOpcode() == Mips::ROLImm) {
3394 uint64_t MaxShift = 32;
3395 uint64_t ShiftValue = ImmValue;
3396 if (ImmValue != 0)
3397 ShiftValue = MaxShift - ImmValue;
3398 emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), Instructions);
3399 return false;
3400 }
3401
3402 if (Inst.getOpcode() == Mips::RORImm) {
3403 emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), Instructions);
3404 return false;
3405 }
3406
3407 return true;
3408 }
3409
3410 if (hasMips32()) {
3411
3412 if (ImmValue == 0) {
3413 emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), Instructions);
3414 return false;
3415 }
3416
3417 switch (Inst.getOpcode()) {
3418 default:
3419 llvm_unreachable("unexpected instruction opcode");
3420 case Mips::ROLImm:
3421 FirstShift = Mips::SLL;
3422 SecondShift = Mips::SRL;
3423 break;
3424 case Mips::RORImm:
3425 FirstShift = Mips::SRL;
3426 SecondShift = Mips::SLL;
3427 break;
3428 }
3429
3430 ATReg = getATReg(Inst.getLoc());
3431 if (!ATReg)
3432 return true;
3433
3434 emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), Instructions);
3435 emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), Instructions);
3436 emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions);
3437
3438 return false;
3439 }
3440
3441 return true;
3442}
3443
3444bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc,
3445 SmallVectorImpl<MCInst> &Instructions) {
3446
3447 unsigned ATReg = Mips::NoRegister;
3448 unsigned DReg = Inst.getOperand(0).getReg();
3449 unsigned SReg = Inst.getOperand(1).getReg();
3450 unsigned TReg = Inst.getOperand(2).getReg();
3451 unsigned TmpReg = DReg;
3452
3453 unsigned FirstShift = Mips::NOP;
3454 unsigned SecondShift = Mips::NOP;
3455
3456 if (hasMips64r2()) {
3457
3458 if (TmpReg == SReg) {
3459 TmpReg = getATReg(Inst.getLoc());
3460 if (!TmpReg)
3461 return true;
3462 }
3463
3464 if (Inst.getOpcode() == Mips::DROL) {
3465 emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions);
3466 emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), Instructions);
3467 return false;
3468 }
3469
3470 if (Inst.getOpcode() == Mips::DROR) {
3471 emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), Instructions);
3472 return false;
3473 }
3474
3475 return true;
3476 }
3477
3478 if (hasMips64()) {
3479
3480 switch (Inst.getOpcode()) {
3481 default:
3482 llvm_unreachable("unexpected instruction opcode");
3483 case Mips::DROL:
3484 FirstShift = Mips::DSRLV;
3485 SecondShift = Mips::DSLLV;
3486 break;
3487 case Mips::DROR:
3488 FirstShift = Mips::DSLLV;
3489 SecondShift = Mips::DSRLV;
3490 break;
3491 }
3492
3493 ATReg = getATReg(Inst.getLoc());
3494 if (!ATReg)
3495 return true;
3496
3497 emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions);
3498 emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), Instructions);
3499 emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), Instructions);
3500 emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions);
3501
3502 return false;
3503 }
3504
3505 return true;
3506}
3507
3508bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
3509 SmallVectorImpl<MCInst> &Instructions) {
3510
3511 unsigned ATReg = Mips::NoRegister;
3512 unsigned DReg = Inst.getOperand(0).getReg();
3513 unsigned SReg = Inst.getOperand(1).getReg();
3514 int64_t ImmValue = Inst.getOperand(2).getImm() % 64;
3515
3516 unsigned FirstShift = Mips::NOP;
3517 unsigned SecondShift = Mips::NOP;
3518
3519 MCInst TmpInst;
3520
3521 if (hasMips64r2()) {
3522
3523 unsigned FinalOpcode = Mips::NOP;
3524 if (ImmValue == 0)
3525 FinalOpcode = Mips::DROTR;
3526 else if (ImmValue % 32 == 0)
3527 FinalOpcode = Mips::DROTR32;
3528 else if ((ImmValue >= 1) && (ImmValue <= 32)) {
3529 if (Inst.getOpcode() == Mips::DROLImm)
3530 FinalOpcode = Mips::DROTR32;
3531 else
3532 FinalOpcode = Mips::DROTR;
3533 } else if (ImmValue >= 33) {
3534 if (Inst.getOpcode() == Mips::DROLImm)
3535 FinalOpcode = Mips::DROTR;
3536 else
3537 FinalOpcode = Mips::DROTR32;
3538 }
3539
3540 uint64_t ShiftValue = ImmValue % 32;
3541 if (Inst.getOpcode() == Mips::DROLImm)
3542 ShiftValue = (32 - ImmValue % 32) % 32;
3543
3544 emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), Instructions);
3545
3546 return false;
3547 }
3548
3549 if (hasMips64()) {
3550
3551 if (ImmValue == 0) {
3552 emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), Instructions);
3553 return false;
3554 }
3555
3556 switch (Inst.getOpcode()) {
3557 default:
3558 llvm_unreachable("unexpected instruction opcode");
3559 case Mips::DROLImm:
3560 if ((ImmValue >= 1) && (ImmValue <= 31)) {
3561 FirstShift = Mips::DSLL;
3562 SecondShift = Mips::DSRL32;
3563 }
3564 if (ImmValue == 32) {
3565 FirstShift = Mips::DSLL32;
3566 SecondShift = Mips::DSRL32;
3567 }
3568 if ((ImmValue >= 33) && (ImmValue <= 63)) {
3569 FirstShift = Mips::DSLL32;
3570 SecondShift = Mips::DSRL;
3571 }
3572 break;
3573 case Mips::DRORImm:
3574 if ((ImmValue >= 1) && (ImmValue <= 31)) {
3575 FirstShift = Mips::DSRL;
3576 SecondShift = Mips::DSLL32;
3577 }
3578 if (ImmValue == 32) {
3579 FirstShift = Mips::DSRL32;
3580 SecondShift = Mips::DSLL32;
3581 }
3582 if ((ImmValue >= 33) && (ImmValue <= 63)) {
3583 FirstShift = Mips::DSRL32;
3584 SecondShift = Mips::DSLL;
3585 }
3586 break;
3587 }
3588
3589 ATReg = getATReg(Inst.getLoc());
3590 if (!ATReg)
3591 return true;
3592
3593 emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), Instructions);
3594 emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32, Inst.getLoc(), Instructions);
3595 emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions);
3596
3597 return false;
3598 }
3599
3600 return true;
3601}
3602
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003603bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc,
3604 SmallVectorImpl<MCInst> &Instructions) {
3605
3606 unsigned FirstRegOp = Inst.getOperand(0).getReg();
3607 unsigned SecondRegOp = Inst.getOperand(1).getReg();
3608
3609 emitRI(Mips::BGEZ, SecondRegOp, 8, IDLoc, Instructions);
3610 if (FirstRegOp != SecondRegOp)
3611 emitRRR(Mips::ADDu, FirstRegOp, SecondRegOp, Mips::ZERO, IDLoc, Instructions);
3612 else
3613 createNop(false, IDLoc, Instructions);
3614 emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, Instructions);
3615
3616 return false;
3617}
3618
Toma Tabacu234482a2015-03-16 12:03:39 +00003619void MipsAsmParser::createNop(bool hasShortDelaySlot, SMLoc IDLoc,
3620 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003621 if (hasShortDelaySlot)
3622 emitRR(Mips::MOVE16_MM, Mips::ZERO, Mips::ZERO, IDLoc, Instructions);
3623 else
3624 emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, Instructions);
Toma Tabacu234482a2015-03-16 12:03:39 +00003625}
3626
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003627void MipsAsmParser::createAddu(unsigned DstReg, unsigned SrcReg,
Toma Tabacu0b3e9782015-06-23 14:00:54 +00003628 unsigned TrgReg, bool Is64Bit,
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003629 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanders03f9c012015-07-14 12:24:22 +00003630 emitRRR(Is64Bit ? Mips::DADDu : Mips::ADDu, DstReg, SrcReg, TrgReg, SMLoc(),
3631 Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003632}
3633
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003634void MipsAsmParser::createCpRestoreMemOp(
3635 bool IsLoad, int StackOffset, SMLoc IDLoc,
3636 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003637 // If the offset can not fit into 16 bits, we need to expand.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003638 if (!isInt<16>(StackOffset)) {
3639 MCInst MemInst;
3640 MemInst.setOpcode(IsLoad ? Mips::LW : Mips::SW);
3641 MemInst.addOperand(MCOperand::createReg(Mips::GP));
3642 MemInst.addOperand(MCOperand::createReg(Mips::SP));
3643 MemInst.addOperand(MCOperand::createImm(StackOffset));
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003644 expandMemInst(MemInst, IDLoc, Instructions, IsLoad, true /*HasImmOpnd*/);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003645 return;
3646 }
3647
3648 emitRRI(IsLoad ? Mips::LW : Mips::SW, Mips::GP, Mips::SP, StackOffset, IDLoc,
3649 Instructions);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003650}
3651
Matheus Almeida595fcab2014-06-11 15:05:56 +00003652unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
3653 // As described by the Mips32r2 spec, the registers Rd and Rs for
3654 // jalr.hb must be different.
3655 unsigned Opcode = Inst.getOpcode();
3656
3657 if (Opcode == Mips::JALR_HB &&
3658 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
3659 return Match_RequiresDifferentSrcAndDst;
3660
3661 return Match_Success;
3662}
3663
Daniel Sanders52da7af2015-11-06 12:11:03 +00003664static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
3665 uint64_t ErrorInfo) {
3666 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
3667 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
3668 if (ErrorLoc == SMLoc())
3669 return Loc;
3670 return ErrorLoc;
3671 }
3672 return Loc;
3673}
3674
David Blaikie960ea3f2014-06-08 16:18:35 +00003675bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3676 OperandVector &Operands,
3677 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003678 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00003679 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00003680
Jack Carterb4dbc172012-09-05 23:34:03 +00003681 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00003682 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00003683 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003684 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00003685
3686 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003687 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003688 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00003689 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00003690 for (unsigned i = 0; i < Instructions.size(); i++)
Akira Hatanakabd9fc282015-11-14 05:20:05 +00003691 Out.EmitInstruction(Instructions[i], getSTI());
Jack Carterb4dbc172012-09-05 23:34:03 +00003692 return false;
3693 }
3694 case Match_MissingFeature:
3695 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
3696 return true;
3697 case Match_InvalidOperand: {
3698 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00003699 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003700 if (ErrorInfo >= Operands.size())
3701 return Error(IDLoc, "too few operands for instruction");
3702
Daniel Sanders52da7af2015-11-06 12:11:03 +00003703 ErrorLoc = Operands[ErrorInfo]->getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00003704 if (ErrorLoc == SMLoc())
3705 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00003706 }
3707
3708 return Error(ErrorLoc, "invalid operand for instruction");
3709 }
3710 case Match_MnemonicFail:
3711 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00003712 case Match_RequiresDifferentSrcAndDst:
3713 return Error(IDLoc, "source and destination must be different");
Daniel Sanders52da7af2015-11-06 12:11:03 +00003714 case Match_Immz:
3715 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00003716 case Match_UImm1_0:
3717 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3718 "expected 1-bit unsigned immediate");
Daniel Sandersea4f6532015-11-06 12:22:31 +00003719 case Match_UImm2_0:
3720 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3721 "expected 2-bit unsigned immediate");
3722 case Match_UImm2_1:
3723 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3724 "expected immediate in range 1 .. 4");
Daniel Sanders38ce0f62015-11-06 12:31:27 +00003725 case Match_UImm3_0:
3726 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3727 "expected 3-bit unsigned immediate");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00003728 case Match_UImm4_0:
3729 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3730 "expected 4-bit unsigned immediate");
Daniel Sanders78e89022016-03-11 11:37:50 +00003731 case Match_SImm4_0:
3732 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3733 "expected 4-bit signed immediate");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00003734 case Match_UImm5_0:
3735 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3736 "expected 5-bit unsigned immediate");
Daniel Sanders0f17d0d2016-03-22 14:29:53 +00003737 case Match_SImm5_0:
3738 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3739 "expected 5-bit signed immediate");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00003740 case Match_UImm5_1:
3741 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3742 "expected immediate in range 1 .. 32");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00003743 case Match_UImm5_32:
3744 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3745 "expected immediate in range 32 .. 63");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00003746 case Match_UImm5_33:
3747 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3748 "expected immediate in range 33 .. 64");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00003749 case Match_UImm5_0_Report_UImm6:
3750 // This is used on UImm5 operands that have a corresponding UImm5_32
3751 // operand to avoid confusing the user.
3752 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3753 "expected 6-bit unsigned immediate");
3754 case Match_UImm5_Lsl2:
3755 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3756 "expected both 7-bit unsigned immediate and multiple of 4");
Hrvoje Varga46458d02016-02-25 12:53:29 +00003757 case Match_UImmRange2_64:
3758 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3759 "expected immediate in range 2 .. 64");
Daniel Sanders59d092f2015-12-08 13:49:19 +00003760 case Match_UImm6_0:
3761 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3762 "expected 6-bit unsigned immediate");
Daniel Sanders19b7f762016-03-14 11:16:56 +00003763 case Match_UImm6_Lsl2:
3764 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3765 "expected both 8-bit unsigned immediate and multiple of 4");
Daniel Sanders78e89022016-03-11 11:37:50 +00003766 case Match_SImm6_0:
Zlatko Buljan252cca52015-12-18 08:59:37 +00003767 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3768 "expected 6-bit signed immediate");
3769 case Match_UImm7_0:
3770 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3771 "expected 7-bit unsigned immediate");
Daniel Sanders97297772016-03-22 14:40:00 +00003772 case Match_UImm7_N1:
3773 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3774 "expected immediate in range -1 .. 126");
3775 case Match_SImm7_Lsl2:
3776 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3777 "expected both 9-bit signed immediate and multiple of 4");
Daniel Sanders106d2d42015-12-08 14:42:10 +00003778 case Match_UImm8_0:
3779 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3780 "expected 8-bit unsigned immediate");
Daniel Sanders3c722312015-12-09 13:48:05 +00003781 case Match_UImm10_0:
3782 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3783 "expected 10-bit unsigned immediate");
Daniel Sanders837f1512016-03-24 13:26:59 +00003784 case Match_SImm10_0:
3785 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3786 "expected 10-bit signed immediate");
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00003787 case Match_UImm16:
3788 case Match_UImm16_Relaxed:
3789 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3790 "expected 16-bit unsigned immediate");
Daniel Sanders03a8d2f2016-02-29 16:06:38 +00003791 case Match_UImm20_0:
3792 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3793 "expected 20-bit unsigned immediate");
Jack Carterb4dbc172012-09-05 23:34:03 +00003794 }
Craig Topper589ceee2015-01-03 08:16:34 +00003795
3796 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00003797}
3798
Toma Tabacud9d344b2015-04-27 14:05:04 +00003799void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
3800 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
3801 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
3802 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003803}
3804
Toma Tabacu81496c12015-05-20 08:54:45 +00003805void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
3806 if (!AssemblerOptions.back()->isMacro())
3807 Warning(Loc, "macro instruction expanded into multiple instructions");
3808}
3809
Daniel Sandersef638fe2014-10-03 15:37:37 +00003810void
3811MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
3812 SMRange Range, bool ShowColors) {
3813 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00003814 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00003815 ShowColors);
3816}
3817
Jack Carter1ac53222013-02-20 23:11:17 +00003818int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003819 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003820
Vladimir Medic4c299852013-11-06 11:27:05 +00003821 CC = StringSwitch<unsigned>(Name)
3822 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003823 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00003824 .Case("a0", 4)
3825 .Case("a1", 5)
3826 .Case("a2", 6)
3827 .Case("a3", 7)
3828 .Case("v0", 2)
3829 .Case("v1", 3)
3830 .Case("s0", 16)
3831 .Case("s1", 17)
3832 .Case("s2", 18)
3833 .Case("s3", 19)
3834 .Case("s4", 20)
3835 .Case("s5", 21)
3836 .Case("s6", 22)
3837 .Case("s7", 23)
3838 .Case("k0", 26)
3839 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003840 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00003841 .Case("sp", 29)
3842 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003843 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00003844 .Case("ra", 31)
3845 .Case("t0", 8)
3846 .Case("t1", 9)
3847 .Case("t2", 10)
3848 .Case("t3", 11)
3849 .Case("t4", 12)
3850 .Case("t5", 13)
3851 .Case("t6", 14)
3852 .Case("t7", 15)
3853 .Case("t8", 24)
3854 .Case("t9", 25)
3855 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003856
Toma Tabacufda445c2014-09-15 15:33:01 +00003857 if (!(isABI_N32() || isABI_N64()))
3858 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003859
Daniel Sandersef638fe2014-10-03 15:37:37 +00003860 if (12 <= CC && CC <= 15) {
3861 // Name is one of t4-t7
3862 AsmToken RegTok = getLexer().peekTok();
3863 SMRange RegRange = RegTok.getLocRange();
3864
3865 StringRef FixedName = StringSwitch<StringRef>(Name)
3866 .Case("t4", "t0")
3867 .Case("t5", "t1")
3868 .Case("t6", "t2")
3869 .Case("t7", "t3")
3870 .Default("");
3871 assert(FixedName != "" && "Register name is not one of t4-t7.");
3872
3873 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
3874 "Did you mean $" + FixedName + "?", RegRange);
3875 }
3876
Toma Tabacufda445c2014-09-15 15:33:01 +00003877 // Although SGI documentation just cuts out t0-t3 for n32/n64,
3878 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
3879 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
3880 if (8 <= CC && CC <= 11)
3881 CC += 4;
3882
3883 if (CC == -1)
3884 CC = StringSwitch<unsigned>(Name)
3885 .Case("a4", 8)
3886 .Case("a5", 9)
3887 .Case("a6", 10)
3888 .Case("a7", 11)
3889 .Case("kt0", 26)
3890 .Case("kt1", 27)
3891 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003892
3893 return CC;
3894}
Jack Carterd0bd6422013-04-18 00:41:53 +00003895
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003896int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
3897 int CC;
3898
3899 CC = StringSwitch<unsigned>(Name)
3900 .Case("hwr_cpunum", 0)
3901 .Case("hwr_synci_step", 1)
3902 .Case("hwr_cc", 2)
3903 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00003904 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003905 .Default(-1);
3906
3907 return CC;
3908}
3909
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003910int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003911
Jack Cartera63b16a2012-09-07 00:23:42 +00003912 if (Name[0] == 'f') {
3913 StringRef NumString = Name.substr(1);
3914 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003915 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 > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00003918 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003919 return IntVal;
3920 }
3921 return -1;
3922}
Jack Cartera63b16a2012-09-07 00:23:42 +00003923
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003924int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
3925
3926 if (Name.startswith("fcc")) {
3927 StringRef NumString = Name.substr(3);
3928 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 > 7) // There are only 8 fcc registers.
3932 return -1;
3933 return IntVal;
3934 }
3935 return -1;
3936}
3937
3938int MipsAsmParser::matchACRegisterName(StringRef Name) {
3939
Akira Hatanaka274d24c2013-08-14 01:15:52 +00003940 if (Name.startswith("ac")) {
3941 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003942 unsigned IntVal;
3943 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003944 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003945 if (IntVal > 3) // There are only 3 acc registers.
3946 return -1;
3947 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00003948 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003949 return -1;
3950}
Jack Carterd0bd6422013-04-18 00:41:53 +00003951
Jack Carter5dc8ac92013-09-25 23:50:44 +00003952int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
3953 unsigned IntVal;
3954
3955 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
3956 return -1;
3957
3958 if (IntVal > 31)
3959 return -1;
3960
3961 return IntVal;
3962}
3963
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003964int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
3965 int CC;
3966
3967 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00003968 .Case("msair", 0)
3969 .Case("msacsr", 1)
3970 .Case("msaaccess", 2)
3971 .Case("msasave", 3)
3972 .Case("msamodify", 4)
3973 .Case("msarequest", 5)
3974 .Case("msamap", 6)
3975 .Case("msaunmap", 7)
3976 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003977
3978 return CC;
3979}
3980
Toma Tabacu89a712b2015-04-15 10:48:56 +00003981unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00003982 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00003983 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00003984 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00003985 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00003986 return 0;
3987 }
3988 unsigned AT = getReg(
3989 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00003990 return AT;
3991}
Jack Carter0b744b32012-10-04 02:29:46 +00003992
Jack Carterd0bd6422013-04-18 00:41:53 +00003993unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00003994 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00003995}
3996
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003997unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003998 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00003999 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004000}
4001
Jack Carter873c7242013-01-12 01:03:14 +00004002int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004003 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00004004 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00004005 return -1;
4006
Jack Carter873c7242013-01-12 01:03:14 +00004007 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00004008}
4009
Toma Tabacu13964452014-09-04 13:23:44 +00004010bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004011 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004012 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004013
Jack Carter30a59822012-10-04 04:03:53 +00004014 // Check if the current operand has a custom associated parser, if so, try to
4015 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00004016 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4017 if (ResTy == MatchOperand_Success)
4018 return false;
4019 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4020 // there was a match, but an error occurred, in which case, just return that
4021 // the operand parsing failed.
4022 if (ResTy == MatchOperand_ParseFail)
4023 return true;
4024
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004025 DEBUG(dbgs() << ".. Generic Parser\n");
4026
Jack Carterb4dbc172012-09-05 23:34:03 +00004027 switch (getLexer().getKind()) {
4028 default:
4029 Error(Parser.getTok().getLoc(), "unexpected token in operand");
4030 return true;
4031 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00004032 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00004033 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00004034
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004035 // Almost all registers have been parsed by custom parsers. There is only
4036 // one exception to this. $zero (and it's alias $0) will reach this point
4037 // for div, divu, and similar instructions because it is not an operand
4038 // to the instruction definition but an explicit register. Special case
4039 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00004040 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00004041 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004042
Jack Carterd0bd6422013-04-18 00:41:53 +00004043 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00004044 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004045 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00004046 return true;
4047
Jack Carter873c7242013-01-12 01:03:14 +00004048 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00004049 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00004050 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00004051 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004052 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00004053
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004054 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004055 return false;
4056 }
Vladimir Medic4c299852013-11-06 11:27:05 +00004057 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00004058 case AsmToken::LParen:
4059 case AsmToken::Minus:
4060 case AsmToken::Plus:
4061 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00004062 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00004063 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004064 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00004065 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004066 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00004067 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00004068 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00004069 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004070 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00004071 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00004072 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00004073 return true;
4074
Jack Carter873c7242013-01-12 01:03:14 +00004075 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4076
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004077 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00004078 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004079 } // case AsmToken::Percent
4080 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00004081 return true;
4082}
4083
Vladimir Medic4c299852013-11-06 11:27:05 +00004084const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00004085 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00004086 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00004087 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00004088 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00004089 // It's a constant, evaluate reloc value.
4090 int16_t Val;
4091 switch (getVariantKind(RelocStr)) {
4092 case MCSymbolRefExpr::VK_Mips_ABS_LO:
4093 // Get the 1st 16-bits.
4094 Val = MCE->getValue() & 0xffff;
4095 break;
4096 case MCSymbolRefExpr::VK_Mips_ABS_HI:
Simon Atanasyan2fc1e3b2016-02-09 22:31:49 +00004097 case MCSymbolRefExpr::VK_Mips_GOT:
Sasa Stankovic06c47802014-04-03 10:37:45 +00004098 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
4099 // 16 bits being negative.
4100 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
4101 break;
4102 case MCSymbolRefExpr::VK_Mips_HIGHER:
4103 // Get the 3rd 16-bits.
4104 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
4105 break;
4106 case MCSymbolRefExpr::VK_Mips_HIGHEST:
4107 // Get the 4th 16-bits.
4108 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
4109 break;
4110 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00004111 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00004112 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00004113 return MCConstantExpr::create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00004114 }
4115
Jack Carterb5cf5902013-04-17 00:18:04 +00004116 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004117 // It's a symbol, create a symbolic expression from the symbol.
Toma Tabacu07c97b32015-06-17 10:43:45 +00004118 const MCSymbol *Symbol = &MSRE->getSymbol();
Jack Carterb5cf5902013-04-17 00:18:04 +00004119 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004120 Res = MCSymbolRefExpr::create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004121 return Res;
4122 }
4123
4124 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00004125 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
4126
Sasa Stankovic06c47802014-04-03 10:37:45 +00004127 // Try to create target expression.
4128 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
Jim Grosbach13760bd2015-05-30 01:25:56 +00004129 return MipsMCExpr::create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00004130
Jack Carterd0bd6422013-04-18 00:41:53 +00004131 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
4132 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004133 Res = MCBinaryExpr::create(BE->getOpcode(), LExp, RExp, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004134 return Res;
4135 }
4136
4137 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004138 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004139 Res = MCUnaryExpr::create(UN->getOpcode(), UnExp, getContext());
Jack Carterd0bd6422013-04-18 00:41:53 +00004140 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00004141 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004142 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00004143 return Expr;
4144}
4145
4146bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
4147
4148 switch (Expr->getKind()) {
4149 case MCExpr::Constant:
4150 return true;
4151 case MCExpr::SymbolRef:
4152 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
4153 case MCExpr::Binary:
4154 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
4155 if (!isEvaluated(BE->getLHS()))
4156 return false;
4157 return isEvaluated(BE->getRHS());
4158 }
4159 case MCExpr::Unary:
4160 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00004161 case MCExpr::Target:
4162 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004163 }
Jack Carterb5cf5902013-04-17 00:18:04 +00004164 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00004165}
Jack Carterd0bd6422013-04-18 00:41:53 +00004166
Jack Carterb5cf5902013-04-17 00:18:04 +00004167bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004168 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00004169 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00004170 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00004171 if (Tok.isNot(AsmToken::Identifier))
4172 return true;
4173
Yaron Keren075759a2015-03-30 15:42:36 +00004174 std::string Str = Tok.getIdentifier();
Jack Carterb5cf5902013-04-17 00:18:04 +00004175
Jack Carterd0bd6422013-04-18 00:41:53 +00004176 Parser.Lex(); // Eat the identifier.
4177 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004178 const MCExpr *IdVal;
4179 SMLoc EndLoc;
4180
4181 if (getLexer().getKind() == AsmToken::LParen) {
4182 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004183 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004184 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004185 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004186 const AsmToken &nextTok = Parser.getTok();
4187 if (nextTok.isNot(AsmToken::Identifier))
4188 return true;
4189 Str += "(%";
4190 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00004191 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00004192 if (getLexer().getKind() != AsmToken::LParen)
4193 return true;
4194 } else
4195 break;
4196 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004197 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00004198 return true;
4199
4200 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00004201 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004202
4203 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00004204 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004205
Jack Carterd0bd6422013-04-18 00:41:53 +00004206 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00004207 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004208}
4209
Jack Carterb4dbc172012-09-05 23:34:03 +00004210bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
4211 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004212 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00004213 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004214 if (ResTy == MatchOperand_Success) {
4215 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00004216 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004217 StartLoc = Operand.getStartLoc();
4218 EndLoc = Operand.getEndLoc();
4219
4220 // AFAIK, we only support numeric registers and named GPR's in CFI
4221 // directives.
4222 // Don't worry about eating tokens before failing. Using an unrecognised
4223 // register is a parse error.
4224 if (Operand.isGPRAsmReg()) {
4225 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004226 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004227 }
4228
4229 return (RegNo == (unsigned)-1);
4230 }
4231
4232 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00004233 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00004234}
4235
Jack Carterb5cf5902013-04-17 00:18:04 +00004236bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004237 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00004238 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00004239 bool Result = true;
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004240 unsigned NumOfLParen = 0;
Jack Carterb5cf5902013-04-17 00:18:04 +00004241
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004242 while (getLexer().getKind() == AsmToken::LParen) {
Jack Carterb5cf5902013-04-17 00:18:04 +00004243 Parser.Lex();
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004244 ++NumOfLParen;
4245 }
Jack Carter873c7242013-01-12 01:03:14 +00004246
Jack Carterd0bd6422013-04-18 00:41:53 +00004247 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00004248 default:
4249 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00004250 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00004251 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00004252 case AsmToken::Integer:
4253 case AsmToken::Minus:
4254 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00004255 if (isParenExpr)
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004256 Result = getParser().parseParenExprOfDepth(NumOfLParen, Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00004257 else
4258 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00004259 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00004260 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004261 break;
Jack Carter873c7242013-01-12 01:03:14 +00004262 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00004263 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00004264 }
Jack Carterb5cf5902013-04-17 00:18:04 +00004265 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004266}
4267
David Blaikie960ea3f2014-06-08 16:18:35 +00004268MipsAsmParser::OperandMatchResultTy
4269MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004270 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004271 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00004272 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00004273 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00004274 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004275 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00004276 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00004277 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00004278
Jack Carterb5cf5902013-04-17 00:18:04 +00004279 if (getLexer().getKind() == AsmToken::LParen) {
4280 Parser.Lex();
4281 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004282 }
4283
Jack Carterb5cf5902013-04-17 00:18:04 +00004284 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004285 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00004286 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004287
Jack Carterd0bd6422013-04-18 00:41:53 +00004288 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004289 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004290 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00004291 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00004292 SMLoc E =
4293 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004294 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00004295 return MatchOperand_Success;
4296 }
4297 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004298 SMLoc E =
4299 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00004300
Jack Carterd0bd6422013-04-18 00:41:53 +00004301 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004302 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00004303 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004304 S, E, *this);
4305 Operands.push_back(
4306 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00004307 return MatchOperand_Success;
4308 }
4309 Error(Parser.getTok().getLoc(), "'(' expected");
4310 return MatchOperand_ParseFail;
4311 }
4312
Jack Carterd0bd6422013-04-18 00:41:53 +00004313 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004314 }
4315
Toma Tabacu13964452014-09-04 13:23:44 +00004316 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004317 if (Res != MatchOperand_Success)
4318 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004319
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004320 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00004321 Error(Parser.getTok().getLoc(), "')' expected");
4322 return MatchOperand_ParseFail;
4323 }
4324
Jack Carter873c7242013-01-12 01:03:14 +00004325 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4326
Jack Carterd0bd6422013-04-18 00:41:53 +00004327 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004328
Craig Topper062a2ba2014-04-25 05:30:21 +00004329 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004330 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00004331
Jack Carterd0bd6422013-04-18 00:41:53 +00004332 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00004333 std::unique_ptr<MipsOperand> op(
4334 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00004335 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004336 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004337 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00004338 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004339 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
4340 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004341 if (IdVal->evaluateAsAbsolute(Imm))
4342 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004343 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004344 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00004345 getContext());
4346 }
4347
David Blaikie960ea3f2014-06-08 16:18:35 +00004348 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004349 return MatchOperand_Success;
4350}
4351
David Blaikie960ea3f2014-06-08 16:18:35 +00004352bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004353 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00004354 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00004355 if (Sym) {
4356 SMLoc S = Parser.getTok().getLoc();
4357 const MCExpr *Expr;
4358 if (Sym->isVariable())
4359 Expr = Sym->getVariableValue();
4360 else
4361 return false;
4362 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004363 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00004364 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00004365 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004366 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004367 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00004368 if (ResTy == MatchOperand_Success) {
4369 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00004370 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00004371 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004372 llvm_unreachable("Should never ParseFail");
4373 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00004374 }
4375 } else if (Expr->getKind() == MCExpr::Constant) {
4376 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00004377 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00004378 Operands.push_back(
4379 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00004380 return true;
4381 }
4382 }
4383 return false;
4384}
Jack Carterd0bd6422013-04-18 00:41:53 +00004385
Jack Carter873c7242013-01-12 01:03:14 +00004386MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004387MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00004388 StringRef Identifier,
4389 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004390 int Index = matchCPURegisterName(Identifier);
4391 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004392 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004393 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4394 return MatchOperand_Success;
4395 }
4396
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004397 Index = matchHWRegsRegisterName(Identifier);
4398 if (Index != -1) {
4399 Operands.push_back(MipsOperand::createHWRegsReg(
4400 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4401 return MatchOperand_Success;
4402 }
4403
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004404 Index = matchFPURegisterName(Identifier);
4405 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004406 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004407 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4408 return MatchOperand_Success;
4409 }
4410
4411 Index = matchFCCRegisterName(Identifier);
4412 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004413 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004414 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4415 return MatchOperand_Success;
4416 }
4417
4418 Index = matchACRegisterName(Identifier);
4419 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004420 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004421 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4422 return MatchOperand_Success;
4423 }
4424
4425 Index = matchMSA128RegisterName(Identifier);
4426 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004427 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004428 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4429 return MatchOperand_Success;
4430 }
4431
4432 Index = matchMSA128CtrlRegisterName(Identifier);
4433 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004434 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004435 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4436 return MatchOperand_Success;
4437 }
4438
4439 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00004440}
4441
4442MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004443MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004444 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00004445 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004446
4447 if (Token.is(AsmToken::Identifier)) {
4448 DEBUG(dbgs() << ".. identifier\n");
4449 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00004450 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004451 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00004452 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004453 } else if (Token.is(AsmToken::Integer)) {
4454 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00004455 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004456 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
4457 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004458 return MatchOperand_Success;
4459 }
4460
4461 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
4462
4463 return MatchOperand_NoMatch;
4464}
4465
David Blaikie960ea3f2014-06-08 16:18:35 +00004466MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004467MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004468 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004469 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004470
4471 auto Token = Parser.getTok();
4472
4473 SMLoc S = Token.getLoc();
4474
4475 if (Token.isNot(AsmToken::Dollar)) {
4476 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
4477 if (Token.is(AsmToken::Identifier)) {
4478 if (searchSymbolAlias(Operands))
4479 return MatchOperand_Success;
4480 }
4481 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
4482 return MatchOperand_NoMatch;
4483 }
4484 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004485
Toma Tabacu13964452014-09-04 13:23:44 +00004486 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00004487 if (ResTy == MatchOperand_Success) {
4488 Parser.Lex(); // $
4489 Parser.Lex(); // identifier
4490 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004491 return ResTy;
4492}
4493
4494MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004495MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004496 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004497 switch (getLexer().getKind()) {
4498 default:
4499 return MatchOperand_NoMatch;
4500 case AsmToken::LParen:
4501 case AsmToken::Minus:
4502 case AsmToken::Plus:
4503 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00004504 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004505 case AsmToken::String:
4506 break;
4507 }
4508
4509 const MCExpr *IdVal;
4510 SMLoc S = Parser.getTok().getLoc();
4511 if (getParser().parseExpression(IdVal))
4512 return MatchOperand_ParseFail;
4513
4514 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4515 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
4516 return MatchOperand_Success;
4517}
4518
David Blaikie960ea3f2014-06-08 16:18:35 +00004519MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004520MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004521 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004522 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004523
4524 SMLoc S = getLexer().getLoc();
4525
4526 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00004527 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004528 if (ResTy != MatchOperand_NoMatch)
4529 return ResTy;
4530
Daniel Sanders315386c2014-04-01 10:40:14 +00004531 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00004532 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00004533 if (ResTy != MatchOperand_NoMatch)
4534 return ResTy;
4535
Daniel Sandersffd84362014-04-01 10:41:48 +00004536 const MCExpr *Expr = nullptr;
4537 if (Parser.parseExpression(Expr)) {
4538 // We have no way of knowing if a symbol was consumed so we must ParseFail
4539 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004540 }
Daniel Sandersffd84362014-04-01 10:41:48 +00004541 Operands.push_back(
4542 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004543 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00004544}
4545
Vladimir Medic2b953d02013-10-01 09:48:56 +00004546MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00004547MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004548 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00004549 const MCExpr *IdVal;
4550 // If the first token is '$' we may have register operand.
4551 if (Parser.getTok().is(AsmToken::Dollar))
4552 return MatchOperand_NoMatch;
4553 SMLoc S = Parser.getTok().getLoc();
4554 if (getParser().parseExpression(IdVal))
4555 return MatchOperand_ParseFail;
4556 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00004557 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00004558 int64_t Val = MCE->getValue();
4559 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4560 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00004561 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00004562 return MatchOperand_Success;
4563}
4564
Matheus Almeida779c5932013-11-18 12:32:49 +00004565MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004566MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004567 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00004568 switch (getLexer().getKind()) {
4569 default:
4570 return MatchOperand_NoMatch;
4571 case AsmToken::LParen:
4572 case AsmToken::Plus:
4573 case AsmToken::Minus:
4574 case AsmToken::Integer:
4575 break;
4576 }
4577
4578 const MCExpr *Expr;
4579 SMLoc S = Parser.getTok().getLoc();
4580
4581 if (getParser().parseExpression(Expr))
4582 return MatchOperand_ParseFail;
4583
4584 int64_t Val;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004585 if (!Expr->evaluateAsAbsolute(Val)) {
Matheus Almeida779c5932013-11-18 12:32:49 +00004586 Error(S, "expected immediate value");
4587 return MatchOperand_ParseFail;
4588 }
4589
4590 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
4591 // and because the CPU always adds one to the immediate field, the allowed
4592 // range becomes 1..4. We'll only check the range here and will deal
4593 // with the addition/subtraction when actually decoding/encoding
4594 // the instruction.
4595 if (Val < 1 || Val > 4) {
4596 Error(S, "immediate not in range (1..4)");
4597 return MatchOperand_ParseFail;
4598 }
4599
Jack Carter3b2c96e2014-01-22 23:31:38 +00004600 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004601 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00004602 return MatchOperand_Success;
4603}
4604
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004605MipsAsmParser::OperandMatchResultTy
4606MipsAsmParser::parseRegisterList(OperandVector &Operands) {
4607 MCAsmParser &Parser = getParser();
4608 SmallVector<unsigned, 10> Regs;
4609 unsigned RegNo;
4610 unsigned PrevReg = Mips::NoRegister;
4611 bool RegRange = false;
4612 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4613
4614 if (Parser.getTok().isNot(AsmToken::Dollar))
4615 return MatchOperand_ParseFail;
4616
4617 SMLoc S = Parser.getTok().getLoc();
4618 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
4619 SMLoc E = getLexer().getLoc();
4620 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
4621 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
4622 if (RegRange) {
4623 // Remove last register operand because registers from register range
4624 // should be inserted first.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004625 if ((isGP64bit() && RegNo == Mips::RA_64) ||
4626 (!isGP64bit() && RegNo == Mips::RA)) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004627 Regs.push_back(RegNo);
4628 } else {
4629 unsigned TmpReg = PrevReg + 1;
4630 while (TmpReg <= RegNo) {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004631 if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) ||
4632 (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) &&
4633 isGP64bit())) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004634 Error(E, "invalid register operand");
4635 return MatchOperand_ParseFail;
4636 }
4637
4638 PrevReg = TmpReg;
4639 Regs.push_back(TmpReg++);
4640 }
4641 }
4642
4643 RegRange = false;
4644 } else {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004645 if ((PrevReg == Mips::NoRegister) &&
4646 ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) ||
4647 (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA)))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004648 Error(E, "$16 or $31 expected");
4649 return MatchOperand_ParseFail;
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004650 } else if (!(((RegNo == Mips::FP || RegNo == Mips::RA ||
4651 (RegNo >= Mips::S0 && RegNo <= Mips::S7)) &&
4652 !isGP64bit()) ||
4653 ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 ||
4654 (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) &&
4655 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004656 Error(E, "invalid register operand");
4657 return MatchOperand_ParseFail;
4658 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004659 ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) ||
4660 (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 &&
4661 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004662 Error(E, "consecutive register numbers expected");
4663 return MatchOperand_ParseFail;
4664 }
4665
4666 Regs.push_back(RegNo);
4667 }
4668
4669 if (Parser.getTok().is(AsmToken::Minus))
4670 RegRange = true;
4671
4672 if (!Parser.getTok().isNot(AsmToken::Minus) &&
4673 !Parser.getTok().isNot(AsmToken::Comma)) {
4674 Error(E, "',' or '-' expected");
4675 return MatchOperand_ParseFail;
4676 }
4677
4678 Lex(); // Consume comma or minus
4679 if (Parser.getTok().isNot(AsmToken::Dollar))
4680 break;
4681
4682 PrevReg = RegNo;
4683 }
4684
4685 SMLoc E = Parser.getTok().getLoc();
4686 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4687 parseMemOperand(Operands);
4688 return MatchOperand_Success;
4689}
4690
Zoran Jovanovic2deca342014-12-16 14:59:10 +00004691MipsAsmParser::OperandMatchResultTy
4692MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
4693 MCAsmParser &Parser = getParser();
4694
4695 SMLoc S = Parser.getTok().getLoc();
4696 if (parseAnyRegister(Operands) != MatchOperand_Success)
4697 return MatchOperand_ParseFail;
4698
4699 SMLoc E = Parser.getTok().getLoc();
4700 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
4701 unsigned Reg = Op.getGPR32Reg();
4702 Operands.pop_back();
4703 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
4704 return MatchOperand_Success;
4705}
4706
Zoran Jovanovic41688672015-02-10 16:36:20 +00004707MipsAsmParser::OperandMatchResultTy
4708MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
4709 MCAsmParser &Parser = getParser();
4710 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4711 SmallVector<unsigned, 10> Regs;
4712
4713 if (Parser.getTok().isNot(AsmToken::Dollar))
4714 return MatchOperand_ParseFail;
4715
4716 SMLoc S = Parser.getTok().getLoc();
4717
4718 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4719 return MatchOperand_ParseFail;
4720
4721 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4722 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4723 Regs.push_back(RegNo);
4724
4725 SMLoc E = Parser.getTok().getLoc();
4726 if (Parser.getTok().isNot(AsmToken::Comma)) {
4727 Error(E, "',' expected");
4728 return MatchOperand_ParseFail;
4729 }
4730
4731 // Remove comma.
4732 Parser.Lex();
4733
4734 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4735 return MatchOperand_ParseFail;
4736
4737 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4738 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4739 Regs.push_back(RegNo);
4740
4741 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4742
4743 return MatchOperand_Success;
4744}
4745
Jack Carterdc1e35d2012-09-06 20:00:02 +00004746MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
4747
Vladimir Medic4c299852013-11-06 11:27:05 +00004748 MCSymbolRefExpr::VariantKind VK =
4749 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
4750 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
4751 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
4752 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
4753 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
4754 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
4755 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
4756 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
4757 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
4758 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
4759 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
4760 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
4761 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
4762 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
4763 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
4764 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
4765 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
4766 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00004767 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
4768 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
4769 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
4770 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
4771 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
4772 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00004773 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
4774 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00004775 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00004776
Matheus Almeida2852af82014-04-22 10:15:54 +00004777 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00004778
Jack Carterdc1e35d2012-09-06 20:00:02 +00004779 return VK;
4780}
Jack Cartera63b16a2012-09-07 00:23:42 +00004781
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004782/// Sometimes (i.e. load/stores) the operand may be followed immediately by
4783/// either this.
4784/// ::= '(', register, ')'
4785/// handle it before we iterate so we don't get tripped up by the lack of
4786/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004787bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004788 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004789 if (getLexer().is(AsmToken::LParen)) {
4790 Operands.push_back(
4791 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
4792 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004793 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004794 SMLoc Loc = getLexer().getLoc();
4795 Parser.eatToEndOfStatement();
4796 return Error(Loc, "unexpected token in argument list");
4797 }
4798 if (Parser.getTok().isNot(AsmToken::RParen)) {
4799 SMLoc Loc = getLexer().getLoc();
4800 Parser.eatToEndOfStatement();
4801 return Error(Loc, "unexpected token, expected ')'");
4802 }
4803 Operands.push_back(
4804 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
4805 Parser.Lex();
4806 }
4807 return false;
4808}
4809
4810/// Sometimes (i.e. in MSA) the operand may be followed immediately by
4811/// either one of these.
4812/// ::= '[', register, ']'
4813/// ::= '[', integer, ']'
4814/// handle it before we iterate so we don't get tripped up by the lack of
4815/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004816bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00004817 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004818 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004819 if (getLexer().is(AsmToken::LBrac)) {
4820 Operands.push_back(
4821 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
4822 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004823 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004824 SMLoc Loc = getLexer().getLoc();
4825 Parser.eatToEndOfStatement();
4826 return Error(Loc, "unexpected token in argument list");
4827 }
4828 if (Parser.getTok().isNot(AsmToken::RBrac)) {
4829 SMLoc Loc = getLexer().getLoc();
4830 Parser.eatToEndOfStatement();
4831 return Error(Loc, "unexpected token, expected ']'");
4832 }
4833 Operands.push_back(
4834 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
4835 Parser.Lex();
4836 }
4837 return false;
4838}
4839
David Blaikie960ea3f2014-06-08 16:18:35 +00004840bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
4841 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004842 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004843 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004844
4845 // We have reached first instruction, module directive are now forbidden.
4846 getTargetStreamer().forbidModuleDirective();
4847
Vladimir Medic74593e62013-07-17 15:00:42 +00004848 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00004849 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00004850 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00004851 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00004852 }
Vladimir Medic64828a12013-07-16 10:07:14 +00004853 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004854 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004855
4856 // Read the remaining operands.
4857 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4858 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004859 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004860 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004861 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004862 return Error(Loc, "unexpected token in argument list");
4863 }
Toma Tabacu13964452014-09-04 13:23:44 +00004864 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004865 return true;
4866 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00004867
Jack Carterd0bd6422013-04-18 00:41:53 +00004868 while (getLexer().is(AsmToken::Comma)) {
4869 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00004870 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004871 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004872 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 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004876 // Parse bracket and parenthesis suffixes before we iterate
4877 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00004878 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004879 return true;
4880 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00004881 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004882 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00004883 }
4884 }
Jack Carterb4dbc172012-09-05 23:34:03 +00004885 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4886 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004887 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004888 return Error(Loc, "unexpected token in argument list");
4889 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004890 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00004891 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00004892}
4893
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004894bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004895 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004896 SMLoc Loc = getLexer().getLoc();
4897 Parser.eatToEndOfStatement();
4898 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00004899}
4900
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004901bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004902 return Error(Loc, ErrorMsg);
4903}
4904
Jack Carter0b744b32012-10-04 02:29:46 +00004905bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004906 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004907 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00004908
4909 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00004910 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00004911
4912 Parser.Lex(); // Eat "noat".
4913
Jack Carterd0bd6422013-04-18 00:41:53 +00004914 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004915 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004916 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004917 return false;
4918 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004919
4920 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004921 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004922 return false;
4923}
Jack Carterd0bd6422013-04-18 00:41:53 +00004924
Jack Carter0b744b32012-10-04 02:29:46 +00004925bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00004926 // Line can be: ".set at", which sets $at to $1
4927 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00004928 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00004929 Parser.Lex(); // Eat "at".
4930
Jack Carter0b744b32012-10-04 02:29:46 +00004931 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004932 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00004933 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00004934
4935 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004936 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004937 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00004938 }
4939
4940 if (getLexer().isNot(AsmToken::Equal)) {
4941 reportParseError("unexpected token, expected equals sign");
4942 return false;
4943 }
4944 Parser.Lex(); // Eat "=".
4945
4946 if (getLexer().isNot(AsmToken::Dollar)) {
4947 if (getLexer().is(AsmToken::EndOfStatement)) {
4948 reportParseError("no register specified");
4949 return false;
4950 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00004951 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00004952 return false;
4953 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004954 }
4955 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00004956
Toma Tabacu16a74492015-02-13 10:30:57 +00004957 // Find out what "reg" is.
4958 unsigned AtRegNo;
4959 const AsmToken &Reg = Parser.getTok();
4960 if (Reg.is(AsmToken::Identifier)) {
4961 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
4962 } else if (Reg.is(AsmToken::Integer)) {
4963 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00004964 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00004965 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00004966 return false;
4967 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004968
4969 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00004970 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004971 reportParseError("invalid register");
4972 return false;
4973 }
4974 Parser.Lex(); // Eat "reg".
4975
4976 // If this is not the end of the statement, report an error.
4977 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4978 reportParseError("unexpected token, expected end of statement");
4979 return false;
4980 }
4981
4982 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
4983
4984 Parser.Lex(); // Consume the EndOfStatement.
4985 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004986}
4987
4988bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004989 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004990 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004991 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004992 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;
4995 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004996 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00004997 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004998 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004999 return false;
5000}
5001
5002bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005003 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005004 Parser.Lex();
5005 // If this is not the end of the statement, report an error.
5006 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;
Jack Carterd0bd6422013-04-18 00:41:53 +00005009 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005010 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00005011 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00005012 Parser.Lex(); // Consume the EndOfStatement.
5013 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005014}
5015
5016bool MipsAsmParser::parseSetMacroDirective() {
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 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00005025 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00005026 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005027 return false;
5028}
5029
5030bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005031 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00005032 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00005033 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005034 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005035 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005036 return false;
5037 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005038 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00005039 reportParseError("`noreorder' must be set before `nomacro'");
5040 return false;
5041 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005042 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00005043 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00005044 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005045 return false;
5046}
Jack Carterd76b2372013-03-21 21:44:16 +00005047
Daniel Sanders44934432014-08-07 12:03:36 +00005048bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005049 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00005050 Parser.Lex();
5051
5052 // If this is not the end of the statement, report an error.
5053 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005054 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00005055
5056 setFeatureBits(Mips::FeatureMSA, "msa");
5057 getTargetStreamer().emitDirectiveSetMsa();
5058 return false;
5059}
5060
5061bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005062 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00005063 Parser.Lex();
5064
5065 // If this is not the end of the statement, report an error.
5066 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005067 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00005068
5069 clearFeatureBits(Mips::FeatureMSA, "msa");
5070 getTargetStreamer().emitDirectiveSetNoMsa();
5071 return false;
5072}
5073
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005074bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005075 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005076 Parser.Lex(); // Eat "nodsp".
5077
5078 // If this is not the end of the statement, report an error.
5079 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5080 reportParseError("unexpected token, expected end of statement");
5081 return false;
5082 }
5083
5084 clearFeatureBits(Mips::FeatureDSP, "dsp");
5085 getTargetStreamer().emitDirectiveSetNoDsp();
5086 return false;
5087}
5088
Toma Tabacucc2502d2014-11-04 17:18:07 +00005089bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005090 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005091 Parser.Lex(); // Eat "mips16".
5092
Jack Carter39536722014-01-22 23:08:42 +00005093 // If this is not the end of the statement, report an error.
5094 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005095 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00005096 return false;
5097 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00005098
5099 setFeatureBits(Mips::FeatureMips16, "mips16");
5100 getTargetStreamer().emitDirectiveSetMips16();
5101 Parser.Lex(); // Consume the EndOfStatement.
5102 return false;
5103}
5104
5105bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005106 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005107 Parser.Lex(); // Eat "nomips16".
5108
5109 // If this is not the end of the statement, report an error.
5110 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5111 reportParseError("unexpected token, expected end of statement");
5112 return false;
5113 }
5114
5115 clearFeatureBits(Mips::FeatureMips16, "mips16");
5116 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00005117 Parser.Lex(); // Consume the EndOfStatement.
5118 return false;
5119}
5120
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005121bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005122 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005123 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005124 // Line can be: .set fp=32
5125 // .set fp=xx
5126 // .set fp=64
5127 Parser.Lex(); // Eat fp token
5128 AsmToken Tok = Parser.getTok();
5129 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005130 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005131 return false;
5132 }
5133 Parser.Lex(); // Eat '=' token.
5134 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005135
5136 if (!parseFpABIValue(FpAbiVal, ".set"))
5137 return false;
5138
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005139 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005140 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005141 return false;
5142 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005143 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005144 Parser.Lex(); // Consume the EndOfStatement.
5145 return false;
5146}
5147
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005148bool MipsAsmParser::parseSetOddSPRegDirective() {
5149 MCAsmParser &Parser = getParser();
5150
5151 Parser.Lex(); // Eat "oddspreg".
5152 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5153 reportParseError("unexpected token, expected end of statement");
5154 return false;
5155 }
5156
5157 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5158 getTargetStreamer().emitDirectiveSetOddSPReg();
5159 return false;
5160}
5161
5162bool MipsAsmParser::parseSetNoOddSPRegDirective() {
5163 MCAsmParser &Parser = getParser();
5164
5165 Parser.Lex(); // Eat "nooddspreg".
5166 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5167 reportParseError("unexpected token, expected end of statement");
5168 return false;
5169 }
5170
5171 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5172 getTargetStreamer().emitDirectiveSetNoOddSPReg();
5173 return false;
5174}
5175
Toma Tabacu9db22db2014-09-09 10:15:38 +00005176bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005177 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005178 SMLoc Loc = getLexer().getLoc();
5179
5180 Parser.Lex();
5181 if (getLexer().isNot(AsmToken::EndOfStatement))
5182 return reportParseError("unexpected token, expected end of statement");
5183
5184 // Always keep an element on the options "stack" to prevent the user
5185 // from changing the initial options. This is how we remember them.
5186 if (AssemblerOptions.size() == 2)
5187 return reportParseError(Loc, ".set pop with no .set push");
5188
Akira Hatanakab11ef082015-11-14 06:35:56 +00005189 MCSubtargetInfo &STI = copySTI();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005190 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005191 setAvailableFeatures(
5192 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
5193 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00005194
5195 getTargetStreamer().emitDirectiveSetPop();
5196 return false;
5197}
5198
5199bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005200 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005201 Parser.Lex();
5202 if (getLexer().isNot(AsmToken::EndOfStatement))
5203 return reportParseError("unexpected token, expected end of statement");
5204
5205 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00005206 AssemblerOptions.push_back(
5207 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00005208
5209 getTargetStreamer().emitDirectiveSetPush();
5210 return false;
5211}
5212
Toma Tabacu29696502015-06-02 09:48:04 +00005213bool MipsAsmParser::parseSetSoftFloatDirective() {
5214 MCAsmParser &Parser = getParser();
5215 Parser.Lex();
5216 if (getLexer().isNot(AsmToken::EndOfStatement))
5217 return reportParseError("unexpected token, expected end of statement");
5218
5219 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5220 getTargetStreamer().emitDirectiveSetSoftFloat();
5221 return false;
5222}
5223
5224bool MipsAsmParser::parseSetHardFloatDirective() {
5225 MCAsmParser &Parser = getParser();
5226 Parser.Lex();
5227 if (getLexer().isNot(AsmToken::EndOfStatement))
5228 return reportParseError("unexpected token, expected end of statement");
5229
5230 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5231 getTargetStreamer().emitDirectiveSetHardFloat();
5232 return false;
5233}
5234
Jack Carterd76b2372013-03-21 21:44:16 +00005235bool MipsAsmParser::parseSetAssignment() {
5236 StringRef Name;
5237 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00005238 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00005239
5240 if (Parser.parseIdentifier(Name))
5241 reportParseError("expected identifier after .set");
5242
5243 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005244 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00005245 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00005246
Jack Carter3b2c96e2014-01-22 23:31:38 +00005247 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00005248 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00005249
Jim Grosbach6f482002015-05-18 18:43:14 +00005250 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00005251 Sym->setVariableValue(Value);
5252
5253 return false;
5254}
Jack Carterd0bd6422013-04-18 00:41:53 +00005255
Toma Tabacu26647792014-09-09 12:52:14 +00005256bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005257 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00005258 Parser.Lex();
5259 if (getLexer().isNot(AsmToken::EndOfStatement))
5260 return reportParseError("unexpected token, expected end of statement");
5261
5262 // Reset assembler options to their initial values.
Akira Hatanakab11ef082015-11-14 06:35:56 +00005263 MCSubtargetInfo &STI = copySTI();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005264 setAvailableFeatures(
5265 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
5266 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00005267 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
5268
5269 getTargetStreamer().emitDirectiveSetMips0();
5270 return false;
5271}
5272
Toma Tabacu85618b32014-08-19 14:22:52 +00005273bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005274 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00005275 Parser.Lex();
5276 if (getLexer().isNot(AsmToken::Equal))
5277 return reportParseError("unexpected token, expected equals sign");
5278
5279 Parser.Lex();
5280 StringRef Arch;
5281 if (Parser.parseIdentifier(Arch))
5282 return reportParseError("expected arch identifier");
5283
5284 StringRef ArchFeatureName =
5285 StringSwitch<StringRef>(Arch)
5286 .Case("mips1", "mips1")
5287 .Case("mips2", "mips2")
5288 .Case("mips3", "mips3")
5289 .Case("mips4", "mips4")
5290 .Case("mips5", "mips5")
5291 .Case("mips32", "mips32")
5292 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005293 .Case("mips32r3", "mips32r3")
5294 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005295 .Case("mips32r6", "mips32r6")
5296 .Case("mips64", "mips64")
5297 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005298 .Case("mips64r3", "mips64r3")
5299 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005300 .Case("mips64r6", "mips64r6")
5301 .Case("cnmips", "cnmips")
5302 .Case("r4000", "mips3") // This is an implementation of Mips3.
5303 .Default("");
5304
5305 if (ArchFeatureName.empty())
5306 return reportParseError("unsupported architecture");
5307
5308 selectArch(ArchFeatureName);
5309 getTargetStreamer().emitDirectiveSetArch(Arch);
5310 return false;
5311}
5312
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005313bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005314 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005315 Parser.Lex();
5316 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005317 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005318
Matheus Almeida2852af82014-04-22 10:15:54 +00005319 switch (Feature) {
5320 default:
5321 llvm_unreachable("Unimplemented feature");
5322 case Mips::FeatureDSP:
5323 setFeatureBits(Mips::FeatureDSP, "dsp");
5324 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005325 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005326 case Mips::FeatureMicroMips:
5327 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005328 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005329 case Mips::FeatureMips1:
5330 selectArch("mips1");
5331 getTargetStreamer().emitDirectiveSetMips1();
5332 break;
5333 case Mips::FeatureMips2:
5334 selectArch("mips2");
5335 getTargetStreamer().emitDirectiveSetMips2();
5336 break;
5337 case Mips::FeatureMips3:
5338 selectArch("mips3");
5339 getTargetStreamer().emitDirectiveSetMips3();
5340 break;
5341 case Mips::FeatureMips4:
5342 selectArch("mips4");
5343 getTargetStreamer().emitDirectiveSetMips4();
5344 break;
5345 case Mips::FeatureMips5:
5346 selectArch("mips5");
5347 getTargetStreamer().emitDirectiveSetMips5();
5348 break;
5349 case Mips::FeatureMips32:
5350 selectArch("mips32");
5351 getTargetStreamer().emitDirectiveSetMips32();
5352 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005353 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005354 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005355 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005356 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005357 case Mips::FeatureMips32r3:
5358 selectArch("mips32r3");
5359 getTargetStreamer().emitDirectiveSetMips32R3();
5360 break;
5361 case Mips::FeatureMips32r5:
5362 selectArch("mips32r5");
5363 getTargetStreamer().emitDirectiveSetMips32R5();
5364 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005365 case Mips::FeatureMips32r6:
5366 selectArch("mips32r6");
5367 getTargetStreamer().emitDirectiveSetMips32R6();
5368 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005369 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005370 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00005371 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005372 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005373 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005374 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005375 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005376 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005377 case Mips::FeatureMips64r3:
5378 selectArch("mips64r3");
5379 getTargetStreamer().emitDirectiveSetMips64R3();
5380 break;
5381 case Mips::FeatureMips64r5:
5382 selectArch("mips64r5");
5383 getTargetStreamer().emitDirectiveSetMips64R5();
5384 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005385 case Mips::FeatureMips64r6:
5386 selectArch("mips64r6");
5387 getTargetStreamer().emitDirectiveSetMips64R6();
5388 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005389 }
5390 return false;
5391}
5392
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005393bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005394 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005395 if (getLexer().isNot(AsmToken::Comma)) {
5396 SMLoc Loc = getLexer().getLoc();
5397 Parser.eatToEndOfStatement();
5398 return Error(Loc, ErrorStr);
5399 }
5400
Matheus Almeida2852af82014-04-22 10:15:54 +00005401 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005402 return true;
5403}
5404
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005405// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
5406// In this class, it is only used for .cprestore.
5407// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
5408// MipsTargetELFStreamer and MipsAsmParser.
5409bool MipsAsmParser::isPicAndNotNxxAbi() {
5410 return inPicMode() && !(isABI_N32() || isABI_N64());
5411}
5412
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005413bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00005414 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00005415 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005416
Toma Tabacudde4c462014-11-06 10:02:45 +00005417 if (inMips16Mode()) {
5418 reportParseError(".cpload is not supported in Mips16 mode");
5419 return false;
5420 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005421
David Blaikie960ea3f2014-06-08 16:18:35 +00005422 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00005423 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005424 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5425 reportParseError("expected register containing function address");
5426 return false;
5427 }
5428
David Blaikie960ea3f2014-06-08 16:18:35 +00005429 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
5430 if (!RegOpnd.isGPRAsmReg()) {
5431 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005432 return false;
5433 }
5434
Toma Tabacudde4c462014-11-06 10:02:45 +00005435 // If this is not the end of the statement, report an error.
5436 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5437 reportParseError("unexpected token, expected end of statement");
5438 return false;
5439 }
5440
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005441 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005442 return false;
5443}
5444
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005445bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
5446 MCAsmParser &Parser = getParser();
5447
5448 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
5449 // is used in non-PIC mode.
5450
5451 if (inMips16Mode()) {
5452 reportParseError(".cprestore is not supported in Mips16 mode");
5453 return false;
5454 }
5455
5456 // Get the stack offset value.
5457 const MCExpr *StackOffset;
5458 int64_t StackOffsetVal;
5459 if (Parser.parseExpression(StackOffset)) {
5460 reportParseError("expected stack offset value");
5461 return false;
5462 }
5463
5464 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
5465 reportParseError("stack offset is not an absolute expression");
5466 return false;
5467 }
5468
5469 if (StackOffsetVal < 0) {
5470 Warning(Loc, ".cprestore with negative stack offset has no effect");
5471 IsCpRestoreSet = false;
5472 } else {
5473 IsCpRestoreSet = true;
5474 CpRestoreOffset = StackOffsetVal;
5475 }
5476
5477 // If this is not the end of the statement, report an error.
5478 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5479 reportParseError("unexpected token, expected end of statement");
5480 return false;
5481 }
5482
5483 // Store the $gp on the stack.
5484 SmallVector<MCInst, 3> StoreInsts;
5485 createCpRestoreMemOp(false /*IsLoad*/, CpRestoreOffset /*StackOffset*/, Loc,
5486 StoreInsts);
5487
5488 getTargetStreamer().emitDirectiveCpRestore(StoreInsts, CpRestoreOffset);
5489 Parser.Lex(); // Consume the EndOfStatement.
5490 return false;
5491}
5492
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005493bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005494 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005495 unsigned FuncReg;
5496 unsigned Save;
5497 bool SaveIsReg = true;
5498
Matheus Almeida7e815762014-06-18 13:08:59 +00005499 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005500 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005501 if (ResTy == MatchOperand_NoMatch) {
5502 reportParseError("expected register containing function address");
5503 Parser.eatToEndOfStatement();
5504 return false;
5505 }
5506
5507 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5508 if (!FuncRegOpnd.isGPRAsmReg()) {
5509 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
5510 Parser.eatToEndOfStatement();
5511 return false;
5512 }
5513
5514 FuncReg = FuncRegOpnd.getGPR32Reg();
5515 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005516
Toma Tabacu65f10572014-09-16 15:00:52 +00005517 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005518 return true;
5519
Toma Tabacu13964452014-09-04 13:23:44 +00005520 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005521 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00005522 const MCExpr *OffsetExpr;
5523 int64_t OffsetVal;
5524 SMLoc ExprLoc = getLexer().getLoc();
5525
5526 if (Parser.parseExpression(OffsetExpr) ||
5527 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
5528 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00005529 Parser.eatToEndOfStatement();
5530 return false;
5531 }
Daniel Sanders5d796282015-09-21 09:26:55 +00005532
5533 Save = OffsetVal;
5534 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00005535 } else {
5536 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5537 if (!SaveOpnd.isGPRAsmReg()) {
5538 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
5539 Parser.eatToEndOfStatement();
5540 return false;
5541 }
5542 Save = SaveOpnd.getGPR32Reg();
5543 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005544
Toma Tabacu65f10572014-09-16 15:00:52 +00005545 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005546 return true;
5547
Toma Tabacu8874eac2015-02-18 13:46:53 +00005548 const MCExpr *Expr;
5549 if (Parser.parseExpression(Expr)) {
5550 reportParseError("expected expression");
5551 return false;
5552 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005553
Toma Tabacu8874eac2015-02-18 13:46:53 +00005554 if (Expr->getKind() != MCExpr::SymbolRef) {
5555 reportParseError("expected symbol");
5556 return false;
5557 }
5558 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
5559
Daniel Sandersf173dda2015-09-22 10:50:09 +00005560 CpSaveLocation = Save;
5561 CpSaveLocationIsRegister = SaveIsReg;
5562
Toma Tabacu8874eac2015-02-18 13:46:53 +00005563 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
5564 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005565 return false;
5566}
5567
Daniel Sandersf173dda2015-09-22 10:50:09 +00005568bool MipsAsmParser::parseDirectiveCPReturn() {
5569 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
5570 CpSaveLocationIsRegister);
5571 return false;
5572}
5573
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005574bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005575 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005576 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5577 const AsmToken &Tok = Parser.getTok();
5578
5579 if (Tok.getString() == "2008") {
5580 Parser.Lex();
5581 getTargetStreamer().emitDirectiveNaN2008();
5582 return false;
5583 } else if (Tok.getString() == "legacy") {
5584 Parser.Lex();
5585 getTargetStreamer().emitDirectiveNaNLegacy();
5586 return false;
5587 }
5588 }
5589 // If we don't recognize the option passed to the .nan
5590 // directive (e.g. no option or unknown option), emit an error.
5591 reportParseError("invalid option in .nan directive");
5592 return false;
5593}
5594
Jack Carter0b744b32012-10-04 02:29:46 +00005595bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005596 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005597 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00005598 const AsmToken &Tok = Parser.getTok();
5599
5600 if (Tok.getString() == "noat") {
5601 return parseSetNoAtDirective();
5602 } else if (Tok.getString() == "at") {
5603 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00005604 } else if (Tok.getString() == "arch") {
5605 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005606 } else if (Tok.getString() == "fp") {
5607 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005608 } else if (Tok.getString() == "oddspreg") {
5609 return parseSetOddSPRegDirective();
5610 } else if (Tok.getString() == "nooddspreg") {
5611 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005612 } else if (Tok.getString() == "pop") {
5613 return parseSetPopDirective();
5614 } else if (Tok.getString() == "push") {
5615 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00005616 } else if (Tok.getString() == "reorder") {
5617 return parseSetReorderDirective();
5618 } else if (Tok.getString() == "noreorder") {
5619 return parseSetNoReorderDirective();
5620 } else if (Tok.getString() == "macro") {
5621 return parseSetMacroDirective();
5622 } else if (Tok.getString() == "nomacro") {
5623 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00005624 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00005625 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005626 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00005627 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005628 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00005629 getTargetStreamer().emitDirectiveSetNoMicroMips();
5630 Parser.eatToEndOfStatement();
5631 return false;
5632 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005633 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00005634 } else if (Tok.getString() == "mips0") {
5635 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00005636 } else if (Tok.getString() == "mips1") {
5637 return parseSetFeature(Mips::FeatureMips1);
5638 } else if (Tok.getString() == "mips2") {
5639 return parseSetFeature(Mips::FeatureMips2);
5640 } else if (Tok.getString() == "mips3") {
5641 return parseSetFeature(Mips::FeatureMips3);
5642 } else if (Tok.getString() == "mips4") {
5643 return parseSetFeature(Mips::FeatureMips4);
5644 } else if (Tok.getString() == "mips5") {
5645 return parseSetFeature(Mips::FeatureMips5);
5646 } else if (Tok.getString() == "mips32") {
5647 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00005648 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005649 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005650 } else if (Tok.getString() == "mips32r3") {
5651 return parseSetFeature(Mips::FeatureMips32r3);
5652 } else if (Tok.getString() == "mips32r5") {
5653 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005654 } else if (Tok.getString() == "mips32r6") {
5655 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005656 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005657 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005658 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005659 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005660 } else if (Tok.getString() == "mips64r3") {
5661 return parseSetFeature(Mips::FeatureMips64r3);
5662 } else if (Tok.getString() == "mips64r5") {
5663 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005664 } else if (Tok.getString() == "mips64r6") {
5665 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00005666 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005667 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005668 } else if (Tok.getString() == "nodsp") {
5669 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00005670 } else if (Tok.getString() == "msa") {
5671 return parseSetMsaDirective();
5672 } else if (Tok.getString() == "nomsa") {
5673 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00005674 } else if (Tok.getString() == "softfloat") {
5675 return parseSetSoftFloatDirective();
5676 } else if (Tok.getString() == "hardfloat") {
5677 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00005678 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00005679 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00005680 parseSetAssignment();
5681 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005682 }
Jack Carter07c818d2013-01-25 01:31:34 +00005683
Jack Carter0b744b32012-10-04 02:29:46 +00005684 return true;
5685}
5686
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005687/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00005688/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005689bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005690 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005691 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5692 for (;;) {
5693 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005694 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00005695 return true;
5696
5697 getParser().getStreamer().EmitValue(Value, Size);
5698
5699 if (getLexer().is(AsmToken::EndOfStatement))
5700 break;
5701
Jack Carter07c818d2013-01-25 01:31:34 +00005702 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005703 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00005704 Parser.Lex();
5705 }
5706 }
5707
5708 Parser.Lex();
5709 return false;
5710}
5711
Vladimir Medic4c299852013-11-06 11:27:05 +00005712/// parseDirectiveGpWord
5713/// ::= .gpword local_sym
5714bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005715 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00005716 const MCExpr *Value;
5717 // EmitGPRel32Value requires an expression, so we are using base class
5718 // method to evaluate the expression.
5719 if (getParser().parseExpression(Value))
5720 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00005721 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00005722
Vladimir Medice10c1122013-11-13 13:18:04 +00005723 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005724 return Error(getLexer().getLoc(),
5725 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00005726 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00005727 return false;
5728}
5729
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005730/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00005731/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005732bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005733 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005734 const MCExpr *Value;
5735 // EmitGPRel64Value requires an expression, so we are using base class
5736 // method to evaluate the expression.
5737 if (getParser().parseExpression(Value))
5738 return true;
5739 getParser().getStreamer().EmitGPRel64Value(Value);
5740
5741 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005742 return Error(getLexer().getLoc(),
5743 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00005744 Parser.Lex(); // Eat EndOfStatement token.
5745 return false;
5746}
5747
Jack Carter0cd3c192014-01-06 23:27:31 +00005748bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005749 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00005750 // Get the option token.
5751 AsmToken Tok = Parser.getTok();
5752 // At the moment only identifiers are supported.
5753 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005754 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00005755 Parser.eatToEndOfStatement();
5756 return false;
5757 }
5758
5759 StringRef Option = Tok.getIdentifier();
5760
5761 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005762 // MipsAsmParser needs to know if the current PIC mode changes.
5763 IsPicEnabled = false;
5764
Jack Carter0cd3c192014-01-06 23:27:31 +00005765 getTargetStreamer().emitDirectiveOptionPic0();
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");
Jack Carter0cd3c192014-01-06 23:27:31 +00005770 Parser.eatToEndOfStatement();
5771 }
5772 return false;
5773 }
5774
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005775 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005776 // MipsAsmParser needs to know if the current PIC mode changes.
5777 IsPicEnabled = true;
5778
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005779 getTargetStreamer().emitDirectiveOptionPic2();
5780 Parser.Lex();
5781 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5782 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005783 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005784 Parser.eatToEndOfStatement();
5785 }
5786 return false;
5787 }
5788
Jack Carter0cd3c192014-01-06 23:27:31 +00005789 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00005790 Warning(Parser.getTok().getLoc(),
5791 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00005792 Parser.eatToEndOfStatement();
5793 return false;
5794}
5795
Toma Tabacu9ca50962015-04-16 09:53:47 +00005796/// parseInsnDirective
5797/// ::= .insn
5798bool MipsAsmParser::parseInsnDirective() {
5799 // If this is not the end of the statement, report an error.
5800 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5801 reportParseError("unexpected token, expected end of statement");
5802 return false;
5803 }
5804
5805 // The actual label marking happens in
5806 // MipsELFStreamer::createPendingLabelRelocs().
5807 getTargetStreamer().emitDirectiveInsn();
5808
5809 getParser().Lex(); // Eat EndOfStatement token.
5810 return false;
5811}
5812
Simon Atanasyanbe186202016-02-11 06:45:54 +00005813/// parseSSectionDirective
5814/// ::= .sbss
5815/// ::= .sdata
5816bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) {
5817 // If this is not the end of the statement, report an error.
5818 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5819 reportParseError("unexpected token, expected end of statement");
5820 return false;
5821 }
5822
5823 MCSection *ELFSection = getContext().getELFSection(
5824 Section, Type, ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL);
5825 getParser().getStreamer().SwitchSection(ELFSection);
5826
5827 getParser().Lex(); // Eat EndOfStatement token.
5828 return false;
5829}
5830
Daniel Sanders7e527422014-07-10 13:38:23 +00005831/// parseDirectiveModule
5832/// ::= .module oddspreg
5833/// ::= .module nooddspreg
5834/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00005835/// ::= .module softfloat
5836/// ::= .module hardfloat
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005837bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005838 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005839 MCAsmLexer &Lexer = getLexer();
5840 SMLoc L = Lexer.getLoc();
5841
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00005842 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005843 // TODO : get a better message.
5844 reportParseError(".module directive must appear before any code");
5845 return false;
5846 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005847
Toma Tabacuc405c822015-01-23 10:40:19 +00005848 StringRef Option;
5849 if (Parser.parseIdentifier(Option)) {
5850 reportParseError("expected .module option identifier");
5851 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005852 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005853
Toma Tabacuc405c822015-01-23 10:40:19 +00005854 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005855 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005856
Toma Tabacu3c499582015-06-25 10:56:57 +00005857 // Synchronize the abiflags information with the FeatureBits information we
5858 // changed above.
5859 getTargetStreamer().updateABIInfo(*this);
5860
5861 // If printing assembly, use the recently updated abiflags information.
5862 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5863 // emitted at the end).
5864 getTargetStreamer().emitDirectiveModuleOddSPReg();
5865
Toma Tabacuc405c822015-01-23 10:40:19 +00005866 // If this is not the end of the statement, report an error.
5867 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5868 reportParseError("unexpected token, expected end of statement");
5869 return false;
5870 }
5871
5872 return false; // parseDirectiveModule has finished successfully.
5873 } else if (Option == "nooddspreg") {
5874 if (!isABI_O32()) {
5875 Error(L, "'.module nooddspreg' requires the O32 ABI");
5876 return false;
5877 }
5878
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005879 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005880
Toma Tabacu3c499582015-06-25 10:56:57 +00005881 // Synchronize the abiflags information with the FeatureBits information we
5882 // changed above.
5883 getTargetStreamer().updateABIInfo(*this);
5884
5885 // If printing assembly, use the recently updated abiflags information.
5886 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5887 // emitted at the end).
5888 getTargetStreamer().emitDirectiveModuleOddSPReg();
5889
Toma Tabacuc405c822015-01-23 10:40:19 +00005890 // If this is not the end of the statement, report an error.
5891 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5892 reportParseError("unexpected token, expected end of statement");
5893 return false;
5894 }
5895
5896 return false; // parseDirectiveModule has finished successfully.
5897 } else if (Option == "fp") {
5898 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00005899 } else if (Option == "softfloat") {
5900 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5901
5902 // Synchronize the ABI Flags information with the FeatureBits information we
5903 // updated above.
5904 getTargetStreamer().updateABIInfo(*this);
5905
5906 // If printing assembly, use the recently updated ABI Flags information.
5907 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5908 // emitted later).
5909 getTargetStreamer().emitDirectiveModuleSoftFloat();
5910
5911 // If this is not the end of the statement, report an error.
5912 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5913 reportParseError("unexpected token, expected end of statement");
5914 return false;
5915 }
5916
5917 return false; // parseDirectiveModule has finished successfully.
5918 } else if (Option == "hardfloat") {
5919 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5920
5921 // Synchronize the ABI Flags information with the FeatureBits information we
5922 // updated above.
5923 getTargetStreamer().updateABIInfo(*this);
5924
5925 // If printing assembly, use the recently updated ABI Flags information.
5926 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5927 // emitted later).
5928 getTargetStreamer().emitDirectiveModuleHardFloat();
5929
5930 // If this is not the end of the statement, report an error.
5931 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5932 reportParseError("unexpected token, expected end of statement");
5933 return false;
5934 }
5935
5936 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00005937 } else {
5938 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
5939 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005940}
5941
5942/// parseDirectiveModuleFP
5943/// ::= =32
5944/// ::= =xx
5945/// ::= =64
5946bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005947 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005948 MCAsmLexer &Lexer = getLexer();
5949
5950 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005951 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005952 return false;
5953 }
5954 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005955
Daniel Sanders7e527422014-07-10 13:38:23 +00005956 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005957 if (!parseFpABIValue(FpABI, ".module"))
5958 return false;
5959
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005960 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005961 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005962 return false;
5963 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005964
Toma Tabacua64e5402015-06-25 12:44:38 +00005965 // Synchronize the abiflags information with the FeatureBits information we
5966 // changed above.
5967 getTargetStreamer().updateABIInfo(*this);
5968
5969 // If printing assembly, use the recently updated abiflags information.
5970 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5971 // emitted at the end).
5972 getTargetStreamer().emitDirectiveModuleFP();
5973
Daniel Sanders7e527422014-07-10 13:38:23 +00005974 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005975 return false;
5976}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005977
Daniel Sanders7e527422014-07-10 13:38:23 +00005978bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005979 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005980 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005981 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005982 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005983
5984 if (Lexer.is(AsmToken::Identifier)) {
5985 StringRef Value = Parser.getTok().getString();
5986 Parser.Lex();
5987
5988 if (Value != "xx") {
5989 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5990 return false;
5991 }
5992
5993 if (!isABI_O32()) {
5994 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
5995 return false;
5996 }
5997
Daniel Sanders7e527422014-07-10 13:38:23 +00005998 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005999 if (ModuleLevelOptions) {
6000 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6001 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6002 } else {
6003 setFeatureBits(Mips::FeatureFPXX, "fpxx");
6004 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
6005 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006006 return true;
6007 }
6008
6009 if (Lexer.is(AsmToken::Integer)) {
6010 unsigned Value = Parser.getTok().getIntVal();
6011 Parser.Lex();
6012
6013 if (Value != 32 && Value != 64) {
6014 reportParseError("unsupported value, expected 'xx', '32' or '64'");
6015 return false;
6016 }
6017
6018 if (Value == 32) {
6019 if (!isABI_O32()) {
6020 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
6021 return false;
6022 }
6023
Daniel Sanders7e527422014-07-10 13:38:23 +00006024 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006025 if (ModuleLevelOptions) {
6026 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6027 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6028 } else {
6029 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
6030 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
6031 }
Toma Tabacua64e5402015-06-25 12:44:38 +00006032 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00006033 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006034 if (ModuleLevelOptions) {
6035 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6036 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6037 } else {
6038 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
6039 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
6040 }
Toma Tabacua64e5402015-06-25 12:44:38 +00006041 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006042
Daniel Sanders7e527422014-07-10 13:38:23 +00006043 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006044 }
6045
6046 return false;
6047}
6048
Jack Carter0b744b32012-10-04 02:29:46 +00006049bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006050 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00006051 StringRef IDVal = DirectiveID.getString();
6052
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006053 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00006054 return parseDirectiveCpLoad(DirectiveID.getLoc());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006055 if (IDVal == ".cprestore")
6056 return parseDirectiveCpRestore(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00006057 if (IDVal == ".dword") {
6058 parseDataDirective(8, DirectiveID.getLoc());
6059 return false;
6060 }
Jack Carterd0bd6422013-04-18 00:41:53 +00006061 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006062 StringRef SymbolName;
6063
6064 if (Parser.parseIdentifier(SymbolName)) {
6065 reportParseError("expected identifier after .ent");
6066 return false;
6067 }
6068
6069 // There's an undocumented extension that allows an integer to
6070 // follow the name of the procedure which AFAICS is ignored by GAS.
6071 // Example: .ent foo,2
6072 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6073 if (getLexer().isNot(AsmToken::Comma)) {
6074 // Even though we accept this undocumented extension for compatibility
6075 // reasons, the additional integer argument does not actually change
6076 // the behaviour of the '.ent' directive, so we would like to discourage
6077 // its use. We do this by not referring to the extended version in
6078 // error messages which are not directly related to its use.
6079 reportParseError("unexpected token, expected end of statement");
6080 return false;
6081 }
6082 Parser.Lex(); // Eat the comma.
6083 const MCExpr *DummyNumber;
6084 int64_t DummyNumberVal;
6085 // If the user was explicitly trying to use the extended version,
6086 // we still give helpful extension-related error messages.
6087 if (Parser.parseExpression(DummyNumber)) {
6088 reportParseError("expected number after comma");
6089 return false;
6090 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00006091 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006092 reportParseError("expected an absolute expression after comma");
6093 return false;
6094 }
6095 }
6096
6097 // If this is not the end of the statement, report an error.
6098 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6099 reportParseError("unexpected token, expected end of statement");
6100 return false;
6101 }
6102
Jim Grosbach6f482002015-05-18 18:43:14 +00006103 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006104
6105 getTargetStreamer().emitDirectiveEnt(*Sym);
6106 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006107 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006108 return false;
6109 }
6110
Jack Carter07c818d2013-01-25 01:31:34 +00006111 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006112 StringRef SymbolName;
6113
6114 if (Parser.parseIdentifier(SymbolName)) {
6115 reportParseError("expected identifier after .end");
6116 return false;
6117 }
6118
6119 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6120 reportParseError("unexpected token, expected end of statement");
6121 return false;
6122 }
6123
6124 if (CurrentFn == nullptr) {
6125 reportParseError(".end used without .ent");
6126 return false;
6127 }
6128
6129 if ((SymbolName != CurrentFn->getName())) {
6130 reportParseError(".end symbol does not match .ent symbol");
6131 return false;
6132 }
6133
6134 getTargetStreamer().emitDirectiveEnd(SymbolName);
6135 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006136 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006137 return false;
6138 }
6139
Jack Carter07c818d2013-01-25 01:31:34 +00006140 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006141 // .frame $stack_reg, frame_size_in_bytes, $return_reg
6142 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00006143 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006144 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6145 reportParseError("expected stack register");
6146 return false;
6147 }
6148
6149 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6150 if (!StackRegOpnd.isGPRAsmReg()) {
6151 reportParseError(StackRegOpnd.getStartLoc(),
6152 "expected general purpose register");
6153 return false;
6154 }
6155 unsigned StackReg = StackRegOpnd.getGPR32Reg();
6156
6157 if (Parser.getTok().is(AsmToken::Comma))
6158 Parser.Lex();
6159 else {
6160 reportParseError("unexpected token, expected comma");
6161 return false;
6162 }
6163
6164 // Parse the frame size.
6165 const MCExpr *FrameSize;
6166 int64_t FrameSizeVal;
6167
6168 if (Parser.parseExpression(FrameSize)) {
6169 reportParseError("expected frame size value");
6170 return false;
6171 }
6172
Jim Grosbach13760bd2015-05-30 01:25:56 +00006173 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006174 reportParseError("frame size not an absolute expression");
6175 return false;
6176 }
6177
6178 if (Parser.getTok().is(AsmToken::Comma))
6179 Parser.Lex();
6180 else {
6181 reportParseError("unexpected token, expected comma");
6182 return false;
6183 }
6184
6185 // Parse the return register.
6186 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00006187 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006188 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6189 reportParseError("expected return register");
6190 return false;
6191 }
6192
6193 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6194 if (!ReturnRegOpnd.isGPRAsmReg()) {
6195 reportParseError(ReturnRegOpnd.getStartLoc(),
6196 "expected general purpose register");
6197 return false;
6198 }
6199
6200 // If this is not the end of the statement, report an error.
6201 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6202 reportParseError("unexpected token, expected end of statement");
6203 return false;
6204 }
6205
6206 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
6207 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006208 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006209 return false;
6210 }
6211
Jack Carter07c818d2013-01-25 01:31:34 +00006212 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00006213 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00006214 }
6215
Daniel Sandersd97a6342014-08-13 10:07:34 +00006216 if (IDVal == ".mask" || IDVal == ".fmask") {
6217 // .mask bitmask, frame_offset
6218 // bitmask: One bit for each register used.
6219 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
6220 // first register is expected to be saved.
6221 // Examples:
6222 // .mask 0x80000000, -4
6223 // .fmask 0x80000000, -4
6224 //
Jack Carterbe332172012-09-07 00:48:02 +00006225
Daniel Sandersd97a6342014-08-13 10:07:34 +00006226 // Parse the bitmask
6227 const MCExpr *BitMask;
6228 int64_t BitMaskVal;
6229
6230 if (Parser.parseExpression(BitMask)) {
6231 reportParseError("expected bitmask value");
6232 return false;
6233 }
6234
Jim Grosbach13760bd2015-05-30 01:25:56 +00006235 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006236 reportParseError("bitmask not an absolute expression");
6237 return false;
6238 }
6239
6240 if (Parser.getTok().is(AsmToken::Comma))
6241 Parser.Lex();
6242 else {
6243 reportParseError("unexpected token, expected comma");
6244 return false;
6245 }
6246
6247 // Parse the frame_offset
6248 const MCExpr *FrameOffset;
6249 int64_t FrameOffsetVal;
6250
6251 if (Parser.parseExpression(FrameOffset)) {
6252 reportParseError("expected frame offset value");
6253 return false;
6254 }
6255
Jim Grosbach13760bd2015-05-30 01:25:56 +00006256 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006257 reportParseError("frame offset not an absolute expression");
6258 return false;
6259 }
6260
6261 // If this is not the end of the statement, report an error.
6262 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6263 reportParseError("unexpected token, expected end of statement");
6264 return false;
6265 }
6266
6267 if (IDVal == ".mask")
6268 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
6269 else
6270 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00006271 return false;
6272 }
6273
Matheus Almeida0051f2d2014-04-16 15:48:55 +00006274 if (IDVal == ".nan")
6275 return parseDirectiveNaN();
6276
Jack Carter07c818d2013-01-25 01:31:34 +00006277 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00006278 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00006279 return false;
6280 }
6281
Rafael Espindolab59fb732014-03-28 18:50:26 +00006282 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00006283 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00006284 return false;
6285 }
6286
Jack Carter07c818d2013-01-25 01:31:34 +00006287 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00006288 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00006289 return false;
6290 }
6291
Scott Egertond1aeb052016-02-15 16:11:51 +00006292 if (IDVal == ".hword") {
6293 parseDataDirective(2, DirectiveID.getLoc());
6294 return false;
6295 }
6296
Jack Carter0cd3c192014-01-06 23:27:31 +00006297 if (IDVal == ".option")
6298 return parseDirectiveOption();
6299
6300 if (IDVal == ".abicalls") {
6301 getTargetStreamer().emitDirectiveAbiCalls();
6302 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006303 Error(Parser.getTok().getLoc(),
6304 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00006305 // Clear line
6306 Parser.eatToEndOfStatement();
6307 }
6308 return false;
6309 }
6310
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006311 if (IDVal == ".cpsetup")
6312 return parseDirectiveCPSetup();
6313
Daniel Sandersf173dda2015-09-22 10:50:09 +00006314 if (IDVal == ".cpreturn")
6315 return parseDirectiveCPReturn();
6316
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006317 if (IDVal == ".module")
6318 return parseDirectiveModule();
6319
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00006320 if (IDVal == ".llvm_internal_mips_reallow_module_directive")
6321 return parseInternalDirectiveReallowModule();
6322
Toma Tabacu9ca50962015-04-16 09:53:47 +00006323 if (IDVal == ".insn")
6324 return parseInsnDirective();
6325
Simon Atanasyanbe186202016-02-11 06:45:54 +00006326 if (IDVal == ".sbss")
6327 return parseSSectionDirective(IDVal, ELF::SHT_NOBITS);
6328 if (IDVal == ".sdata")
6329 return parseSSectionDirective(IDVal, ELF::SHT_PROGBITS);
6330
Rafael Espindola870c4e92012-01-11 03:56:41 +00006331 return true;
6332}
6333
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00006334bool MipsAsmParser::parseInternalDirectiveReallowModule() {
6335 // If this is not the end of the statement, report an error.
6336 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6337 reportParseError("unexpected token, expected end of statement");
6338 return false;
6339 }
6340
6341 getTargetStreamer().reallowModuleDirective();
6342
6343 getParser().Lex(); // Eat EndOfStatement token.
6344 return false;
6345}
6346
Rafael Espindola870c4e92012-01-11 03:56:41 +00006347extern "C" void LLVMInitializeMipsAsmParser() {
6348 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
6349 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
6350 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
6351 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
6352}
Jack Carterb4dbc172012-09-05 23:34:03 +00006353
6354#define GET_REGISTER_MATCHER
6355#define GET_MATCHER_IMPLEMENTATION
6356#include "MipsGenAsmMatcher.inc"