blob: 1a1682d2a12ee01143ff7e3dfbaced39d1243324 [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 Sandersf8bb23e2016-02-01 15:13:31 +00003784 case Match_UImm16:
3785 case Match_UImm16_Relaxed:
3786 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3787 "expected 16-bit unsigned immediate");
Daniel Sanders03a8d2f2016-02-29 16:06:38 +00003788 case Match_UImm20_0:
3789 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3790 "expected 20-bit unsigned immediate");
Jack Carterb4dbc172012-09-05 23:34:03 +00003791 }
Craig Topper589ceee2015-01-03 08:16:34 +00003792
3793 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00003794}
3795
Toma Tabacud9d344b2015-04-27 14:05:04 +00003796void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
3797 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
3798 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
3799 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003800}
3801
Toma Tabacu81496c12015-05-20 08:54:45 +00003802void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
3803 if (!AssemblerOptions.back()->isMacro())
3804 Warning(Loc, "macro instruction expanded into multiple instructions");
3805}
3806
Daniel Sandersef638fe2014-10-03 15:37:37 +00003807void
3808MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
3809 SMRange Range, bool ShowColors) {
3810 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00003811 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00003812 ShowColors);
3813}
3814
Jack Carter1ac53222013-02-20 23:11:17 +00003815int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003816 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003817
Vladimir Medic4c299852013-11-06 11:27:05 +00003818 CC = StringSwitch<unsigned>(Name)
3819 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003820 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00003821 .Case("a0", 4)
3822 .Case("a1", 5)
3823 .Case("a2", 6)
3824 .Case("a3", 7)
3825 .Case("v0", 2)
3826 .Case("v1", 3)
3827 .Case("s0", 16)
3828 .Case("s1", 17)
3829 .Case("s2", 18)
3830 .Case("s3", 19)
3831 .Case("s4", 20)
3832 .Case("s5", 21)
3833 .Case("s6", 22)
3834 .Case("s7", 23)
3835 .Case("k0", 26)
3836 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003837 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00003838 .Case("sp", 29)
3839 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003840 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00003841 .Case("ra", 31)
3842 .Case("t0", 8)
3843 .Case("t1", 9)
3844 .Case("t2", 10)
3845 .Case("t3", 11)
3846 .Case("t4", 12)
3847 .Case("t5", 13)
3848 .Case("t6", 14)
3849 .Case("t7", 15)
3850 .Case("t8", 24)
3851 .Case("t9", 25)
3852 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003853
Toma Tabacufda445c2014-09-15 15:33:01 +00003854 if (!(isABI_N32() || isABI_N64()))
3855 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003856
Daniel Sandersef638fe2014-10-03 15:37:37 +00003857 if (12 <= CC && CC <= 15) {
3858 // Name is one of t4-t7
3859 AsmToken RegTok = getLexer().peekTok();
3860 SMRange RegRange = RegTok.getLocRange();
3861
3862 StringRef FixedName = StringSwitch<StringRef>(Name)
3863 .Case("t4", "t0")
3864 .Case("t5", "t1")
3865 .Case("t6", "t2")
3866 .Case("t7", "t3")
3867 .Default("");
3868 assert(FixedName != "" && "Register name is not one of t4-t7.");
3869
3870 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
3871 "Did you mean $" + FixedName + "?", RegRange);
3872 }
3873
Toma Tabacufda445c2014-09-15 15:33:01 +00003874 // Although SGI documentation just cuts out t0-t3 for n32/n64,
3875 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
3876 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
3877 if (8 <= CC && CC <= 11)
3878 CC += 4;
3879
3880 if (CC == -1)
3881 CC = StringSwitch<unsigned>(Name)
3882 .Case("a4", 8)
3883 .Case("a5", 9)
3884 .Case("a6", 10)
3885 .Case("a7", 11)
3886 .Case("kt0", 26)
3887 .Case("kt1", 27)
3888 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003889
3890 return CC;
3891}
Jack Carterd0bd6422013-04-18 00:41:53 +00003892
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003893int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
3894 int CC;
3895
3896 CC = StringSwitch<unsigned>(Name)
3897 .Case("hwr_cpunum", 0)
3898 .Case("hwr_synci_step", 1)
3899 .Case("hwr_cc", 2)
3900 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00003901 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003902 .Default(-1);
3903
3904 return CC;
3905}
3906
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003907int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003908
Jack Cartera63b16a2012-09-07 00:23:42 +00003909 if (Name[0] == 'f') {
3910 StringRef NumString = Name.substr(1);
3911 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003912 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003913 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003914 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00003915 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003916 return IntVal;
3917 }
3918 return -1;
3919}
Jack Cartera63b16a2012-09-07 00:23:42 +00003920
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003921int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
3922
3923 if (Name.startswith("fcc")) {
3924 StringRef NumString = Name.substr(3);
3925 unsigned IntVal;
3926 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003927 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003928 if (IntVal > 7) // There are only 8 fcc registers.
3929 return -1;
3930 return IntVal;
3931 }
3932 return -1;
3933}
3934
3935int MipsAsmParser::matchACRegisterName(StringRef Name) {
3936
Akira Hatanaka274d24c2013-08-14 01:15:52 +00003937 if (Name.startswith("ac")) {
3938 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003939 unsigned IntVal;
3940 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003941 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003942 if (IntVal > 3) // There are only 3 acc registers.
3943 return -1;
3944 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00003945 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003946 return -1;
3947}
Jack Carterd0bd6422013-04-18 00:41:53 +00003948
Jack Carter5dc8ac92013-09-25 23:50:44 +00003949int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
3950 unsigned IntVal;
3951
3952 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
3953 return -1;
3954
3955 if (IntVal > 31)
3956 return -1;
3957
3958 return IntVal;
3959}
3960
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003961int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
3962 int CC;
3963
3964 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00003965 .Case("msair", 0)
3966 .Case("msacsr", 1)
3967 .Case("msaaccess", 2)
3968 .Case("msasave", 3)
3969 .Case("msamodify", 4)
3970 .Case("msarequest", 5)
3971 .Case("msamap", 6)
3972 .Case("msaunmap", 7)
3973 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003974
3975 return CC;
3976}
3977
Toma Tabacu89a712b2015-04-15 10:48:56 +00003978unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00003979 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00003980 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00003981 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00003982 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00003983 return 0;
3984 }
3985 unsigned AT = getReg(
3986 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00003987 return AT;
3988}
Jack Carter0b744b32012-10-04 02:29:46 +00003989
Jack Carterd0bd6422013-04-18 00:41:53 +00003990unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00003991 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00003992}
3993
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003994unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003995 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00003996 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003997}
3998
Jack Carter873c7242013-01-12 01:03:14 +00003999int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004000 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00004001 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00004002 return -1;
4003
Jack Carter873c7242013-01-12 01:03:14 +00004004 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00004005}
4006
Toma Tabacu13964452014-09-04 13:23:44 +00004007bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004008 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004009 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004010
Jack Carter30a59822012-10-04 04:03:53 +00004011 // Check if the current operand has a custom associated parser, if so, try to
4012 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00004013 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4014 if (ResTy == MatchOperand_Success)
4015 return false;
4016 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4017 // there was a match, but an error occurred, in which case, just return that
4018 // the operand parsing failed.
4019 if (ResTy == MatchOperand_ParseFail)
4020 return true;
4021
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004022 DEBUG(dbgs() << ".. Generic Parser\n");
4023
Jack Carterb4dbc172012-09-05 23:34:03 +00004024 switch (getLexer().getKind()) {
4025 default:
4026 Error(Parser.getTok().getLoc(), "unexpected token in operand");
4027 return true;
4028 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00004029 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00004030 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00004031
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004032 // Almost all registers have been parsed by custom parsers. There is only
4033 // one exception to this. $zero (and it's alias $0) will reach this point
4034 // for div, divu, and similar instructions because it is not an operand
4035 // to the instruction definition but an explicit register. Special case
4036 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00004037 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00004038 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004039
Jack Carterd0bd6422013-04-18 00:41:53 +00004040 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00004041 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004042 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00004043 return true;
4044
Jack Carter873c7242013-01-12 01:03:14 +00004045 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00004046 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00004047 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00004048 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004049 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00004050
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004051 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004052 return false;
4053 }
Vladimir Medic4c299852013-11-06 11:27:05 +00004054 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00004055 case AsmToken::LParen:
4056 case AsmToken::Minus:
4057 case AsmToken::Plus:
4058 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00004059 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00004060 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004061 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00004062 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004063 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00004064 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00004065 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00004066 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004067 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00004068 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00004069 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00004070 return true;
4071
Jack Carter873c7242013-01-12 01:03:14 +00004072 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4073
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004074 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00004075 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004076 } // case AsmToken::Percent
4077 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00004078 return true;
4079}
4080
Vladimir Medic4c299852013-11-06 11:27:05 +00004081const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00004082 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00004083 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00004084 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00004085 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00004086 // It's a constant, evaluate reloc value.
4087 int16_t Val;
4088 switch (getVariantKind(RelocStr)) {
4089 case MCSymbolRefExpr::VK_Mips_ABS_LO:
4090 // Get the 1st 16-bits.
4091 Val = MCE->getValue() & 0xffff;
4092 break;
4093 case MCSymbolRefExpr::VK_Mips_ABS_HI:
Simon Atanasyan2fc1e3b2016-02-09 22:31:49 +00004094 case MCSymbolRefExpr::VK_Mips_GOT:
Sasa Stankovic06c47802014-04-03 10:37:45 +00004095 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
4096 // 16 bits being negative.
4097 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
4098 break;
4099 case MCSymbolRefExpr::VK_Mips_HIGHER:
4100 // Get the 3rd 16-bits.
4101 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
4102 break;
4103 case MCSymbolRefExpr::VK_Mips_HIGHEST:
4104 // Get the 4th 16-bits.
4105 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
4106 break;
4107 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00004108 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00004109 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00004110 return MCConstantExpr::create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00004111 }
4112
Jack Carterb5cf5902013-04-17 00:18:04 +00004113 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004114 // It's a symbol, create a symbolic expression from the symbol.
Toma Tabacu07c97b32015-06-17 10:43:45 +00004115 const MCSymbol *Symbol = &MSRE->getSymbol();
Jack Carterb5cf5902013-04-17 00:18:04 +00004116 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004117 Res = MCSymbolRefExpr::create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004118 return Res;
4119 }
4120
4121 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00004122 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
4123
Sasa Stankovic06c47802014-04-03 10:37:45 +00004124 // Try to create target expression.
4125 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
Jim Grosbach13760bd2015-05-30 01:25:56 +00004126 return MipsMCExpr::create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00004127
Jack Carterd0bd6422013-04-18 00:41:53 +00004128 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
4129 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004130 Res = MCBinaryExpr::create(BE->getOpcode(), LExp, RExp, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004131 return Res;
4132 }
4133
4134 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004135 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004136 Res = MCUnaryExpr::create(UN->getOpcode(), UnExp, getContext());
Jack Carterd0bd6422013-04-18 00:41:53 +00004137 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00004138 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004139 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00004140 return Expr;
4141}
4142
4143bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
4144
4145 switch (Expr->getKind()) {
4146 case MCExpr::Constant:
4147 return true;
4148 case MCExpr::SymbolRef:
4149 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
4150 case MCExpr::Binary:
4151 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
4152 if (!isEvaluated(BE->getLHS()))
4153 return false;
4154 return isEvaluated(BE->getRHS());
4155 }
4156 case MCExpr::Unary:
4157 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00004158 case MCExpr::Target:
4159 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004160 }
Jack Carterb5cf5902013-04-17 00:18:04 +00004161 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00004162}
Jack Carterd0bd6422013-04-18 00:41:53 +00004163
Jack Carterb5cf5902013-04-17 00:18:04 +00004164bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004165 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00004166 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00004167 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00004168 if (Tok.isNot(AsmToken::Identifier))
4169 return true;
4170
Yaron Keren075759a2015-03-30 15:42:36 +00004171 std::string Str = Tok.getIdentifier();
Jack Carterb5cf5902013-04-17 00:18:04 +00004172
Jack Carterd0bd6422013-04-18 00:41:53 +00004173 Parser.Lex(); // Eat the identifier.
4174 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004175 const MCExpr *IdVal;
4176 SMLoc EndLoc;
4177
4178 if (getLexer().getKind() == AsmToken::LParen) {
4179 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004180 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004181 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004182 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004183 const AsmToken &nextTok = Parser.getTok();
4184 if (nextTok.isNot(AsmToken::Identifier))
4185 return true;
4186 Str += "(%";
4187 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00004188 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00004189 if (getLexer().getKind() != AsmToken::LParen)
4190 return true;
4191 } else
4192 break;
4193 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004194 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00004195 return true;
4196
4197 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00004198 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004199
4200 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00004201 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004202
Jack Carterd0bd6422013-04-18 00:41:53 +00004203 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00004204 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004205}
4206
Jack Carterb4dbc172012-09-05 23:34:03 +00004207bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
4208 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004209 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00004210 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004211 if (ResTy == MatchOperand_Success) {
4212 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00004213 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004214 StartLoc = Operand.getStartLoc();
4215 EndLoc = Operand.getEndLoc();
4216
4217 // AFAIK, we only support numeric registers and named GPR's in CFI
4218 // directives.
4219 // Don't worry about eating tokens before failing. Using an unrecognised
4220 // register is a parse error.
4221 if (Operand.isGPRAsmReg()) {
4222 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004223 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004224 }
4225
4226 return (RegNo == (unsigned)-1);
4227 }
4228
4229 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00004230 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00004231}
4232
Jack Carterb5cf5902013-04-17 00:18:04 +00004233bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004234 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00004235 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00004236 bool Result = true;
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004237 unsigned NumOfLParen = 0;
Jack Carterb5cf5902013-04-17 00:18:04 +00004238
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004239 while (getLexer().getKind() == AsmToken::LParen) {
Jack Carterb5cf5902013-04-17 00:18:04 +00004240 Parser.Lex();
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004241 ++NumOfLParen;
4242 }
Jack Carter873c7242013-01-12 01:03:14 +00004243
Jack Carterd0bd6422013-04-18 00:41:53 +00004244 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00004245 default:
4246 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00004247 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00004248 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00004249 case AsmToken::Integer:
4250 case AsmToken::Minus:
4251 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00004252 if (isParenExpr)
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004253 Result = getParser().parseParenExprOfDepth(NumOfLParen, Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00004254 else
4255 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00004256 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00004257 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004258 break;
Jack Carter873c7242013-01-12 01:03:14 +00004259 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00004260 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00004261 }
Jack Carterb5cf5902013-04-17 00:18:04 +00004262 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004263}
4264
David Blaikie960ea3f2014-06-08 16:18:35 +00004265MipsAsmParser::OperandMatchResultTy
4266MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004267 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004268 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00004269 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00004270 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00004271 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004272 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00004273 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00004274 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00004275
Jack Carterb5cf5902013-04-17 00:18:04 +00004276 if (getLexer().getKind() == AsmToken::LParen) {
4277 Parser.Lex();
4278 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004279 }
4280
Jack Carterb5cf5902013-04-17 00:18:04 +00004281 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004282 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00004283 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004284
Jack Carterd0bd6422013-04-18 00:41:53 +00004285 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004286 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004287 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00004288 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00004289 SMLoc E =
4290 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004291 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00004292 return MatchOperand_Success;
4293 }
4294 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004295 SMLoc E =
4296 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00004297
Jack Carterd0bd6422013-04-18 00:41:53 +00004298 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004299 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00004300 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004301 S, E, *this);
4302 Operands.push_back(
4303 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00004304 return MatchOperand_Success;
4305 }
4306 Error(Parser.getTok().getLoc(), "'(' expected");
4307 return MatchOperand_ParseFail;
4308 }
4309
Jack Carterd0bd6422013-04-18 00:41:53 +00004310 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004311 }
4312
Toma Tabacu13964452014-09-04 13:23:44 +00004313 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004314 if (Res != MatchOperand_Success)
4315 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004316
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004317 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00004318 Error(Parser.getTok().getLoc(), "')' expected");
4319 return MatchOperand_ParseFail;
4320 }
4321
Jack Carter873c7242013-01-12 01:03:14 +00004322 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4323
Jack Carterd0bd6422013-04-18 00:41:53 +00004324 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004325
Craig Topper062a2ba2014-04-25 05:30:21 +00004326 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004327 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00004328
Jack Carterd0bd6422013-04-18 00:41:53 +00004329 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00004330 std::unique_ptr<MipsOperand> op(
4331 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00004332 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004333 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004334 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00004335 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004336 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
4337 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004338 if (IdVal->evaluateAsAbsolute(Imm))
4339 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004340 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004341 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00004342 getContext());
4343 }
4344
David Blaikie960ea3f2014-06-08 16:18:35 +00004345 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004346 return MatchOperand_Success;
4347}
4348
David Blaikie960ea3f2014-06-08 16:18:35 +00004349bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004350 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00004351 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00004352 if (Sym) {
4353 SMLoc S = Parser.getTok().getLoc();
4354 const MCExpr *Expr;
4355 if (Sym->isVariable())
4356 Expr = Sym->getVariableValue();
4357 else
4358 return false;
4359 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004360 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00004361 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00004362 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004363 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004364 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00004365 if (ResTy == MatchOperand_Success) {
4366 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00004367 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00004368 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004369 llvm_unreachable("Should never ParseFail");
4370 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00004371 }
4372 } else if (Expr->getKind() == MCExpr::Constant) {
4373 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00004374 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00004375 Operands.push_back(
4376 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00004377 return true;
4378 }
4379 }
4380 return false;
4381}
Jack Carterd0bd6422013-04-18 00:41:53 +00004382
Jack Carter873c7242013-01-12 01:03:14 +00004383MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004384MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00004385 StringRef Identifier,
4386 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004387 int Index = matchCPURegisterName(Identifier);
4388 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004389 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004390 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4391 return MatchOperand_Success;
4392 }
4393
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004394 Index = matchHWRegsRegisterName(Identifier);
4395 if (Index != -1) {
4396 Operands.push_back(MipsOperand::createHWRegsReg(
4397 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4398 return MatchOperand_Success;
4399 }
4400
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004401 Index = matchFPURegisterName(Identifier);
4402 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004403 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004404 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4405 return MatchOperand_Success;
4406 }
4407
4408 Index = matchFCCRegisterName(Identifier);
4409 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004410 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004411 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4412 return MatchOperand_Success;
4413 }
4414
4415 Index = matchACRegisterName(Identifier);
4416 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004417 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004418 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4419 return MatchOperand_Success;
4420 }
4421
4422 Index = matchMSA128RegisterName(Identifier);
4423 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004424 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004425 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4426 return MatchOperand_Success;
4427 }
4428
4429 Index = matchMSA128CtrlRegisterName(Identifier);
4430 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004431 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004432 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4433 return MatchOperand_Success;
4434 }
4435
4436 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00004437}
4438
4439MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004440MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004441 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00004442 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004443
4444 if (Token.is(AsmToken::Identifier)) {
4445 DEBUG(dbgs() << ".. identifier\n");
4446 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00004447 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004448 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00004449 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004450 } else if (Token.is(AsmToken::Integer)) {
4451 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00004452 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004453 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
4454 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004455 return MatchOperand_Success;
4456 }
4457
4458 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
4459
4460 return MatchOperand_NoMatch;
4461}
4462
David Blaikie960ea3f2014-06-08 16:18:35 +00004463MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004464MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004465 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004466 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004467
4468 auto Token = Parser.getTok();
4469
4470 SMLoc S = Token.getLoc();
4471
4472 if (Token.isNot(AsmToken::Dollar)) {
4473 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
4474 if (Token.is(AsmToken::Identifier)) {
4475 if (searchSymbolAlias(Operands))
4476 return MatchOperand_Success;
4477 }
4478 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
4479 return MatchOperand_NoMatch;
4480 }
4481 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004482
Toma Tabacu13964452014-09-04 13:23:44 +00004483 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00004484 if (ResTy == MatchOperand_Success) {
4485 Parser.Lex(); // $
4486 Parser.Lex(); // identifier
4487 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004488 return ResTy;
4489}
4490
4491MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004492MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004493 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004494 switch (getLexer().getKind()) {
4495 default:
4496 return MatchOperand_NoMatch;
4497 case AsmToken::LParen:
4498 case AsmToken::Minus:
4499 case AsmToken::Plus:
4500 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00004501 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004502 case AsmToken::String:
4503 break;
4504 }
4505
4506 const MCExpr *IdVal;
4507 SMLoc S = Parser.getTok().getLoc();
4508 if (getParser().parseExpression(IdVal))
4509 return MatchOperand_ParseFail;
4510
4511 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4512 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
4513 return MatchOperand_Success;
4514}
4515
David Blaikie960ea3f2014-06-08 16:18:35 +00004516MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004517MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004518 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004519 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004520
4521 SMLoc S = getLexer().getLoc();
4522
4523 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00004524 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004525 if (ResTy != MatchOperand_NoMatch)
4526 return ResTy;
4527
Daniel Sanders315386c2014-04-01 10:40:14 +00004528 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00004529 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00004530 if (ResTy != MatchOperand_NoMatch)
4531 return ResTy;
4532
Daniel Sandersffd84362014-04-01 10:41:48 +00004533 const MCExpr *Expr = nullptr;
4534 if (Parser.parseExpression(Expr)) {
4535 // We have no way of knowing if a symbol was consumed so we must ParseFail
4536 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004537 }
Daniel Sandersffd84362014-04-01 10:41:48 +00004538 Operands.push_back(
4539 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004540 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00004541}
4542
Vladimir Medic2b953d02013-10-01 09:48:56 +00004543MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00004544MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004545 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00004546 const MCExpr *IdVal;
4547 // If the first token is '$' we may have register operand.
4548 if (Parser.getTok().is(AsmToken::Dollar))
4549 return MatchOperand_NoMatch;
4550 SMLoc S = Parser.getTok().getLoc();
4551 if (getParser().parseExpression(IdVal))
4552 return MatchOperand_ParseFail;
4553 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00004554 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00004555 int64_t Val = MCE->getValue();
4556 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4557 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00004558 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00004559 return MatchOperand_Success;
4560}
4561
Matheus Almeida779c5932013-11-18 12:32:49 +00004562MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004563MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004564 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00004565 switch (getLexer().getKind()) {
4566 default:
4567 return MatchOperand_NoMatch;
4568 case AsmToken::LParen:
4569 case AsmToken::Plus:
4570 case AsmToken::Minus:
4571 case AsmToken::Integer:
4572 break;
4573 }
4574
4575 const MCExpr *Expr;
4576 SMLoc S = Parser.getTok().getLoc();
4577
4578 if (getParser().parseExpression(Expr))
4579 return MatchOperand_ParseFail;
4580
4581 int64_t Val;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004582 if (!Expr->evaluateAsAbsolute(Val)) {
Matheus Almeida779c5932013-11-18 12:32:49 +00004583 Error(S, "expected immediate value");
4584 return MatchOperand_ParseFail;
4585 }
4586
4587 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
4588 // and because the CPU always adds one to the immediate field, the allowed
4589 // range becomes 1..4. We'll only check the range here and will deal
4590 // with the addition/subtraction when actually decoding/encoding
4591 // the instruction.
4592 if (Val < 1 || Val > 4) {
4593 Error(S, "immediate not in range (1..4)");
4594 return MatchOperand_ParseFail;
4595 }
4596
Jack Carter3b2c96e2014-01-22 23:31:38 +00004597 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004598 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00004599 return MatchOperand_Success;
4600}
4601
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004602MipsAsmParser::OperandMatchResultTy
4603MipsAsmParser::parseRegisterList(OperandVector &Operands) {
4604 MCAsmParser &Parser = getParser();
4605 SmallVector<unsigned, 10> Regs;
4606 unsigned RegNo;
4607 unsigned PrevReg = Mips::NoRegister;
4608 bool RegRange = false;
4609 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4610
4611 if (Parser.getTok().isNot(AsmToken::Dollar))
4612 return MatchOperand_ParseFail;
4613
4614 SMLoc S = Parser.getTok().getLoc();
4615 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
4616 SMLoc E = getLexer().getLoc();
4617 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
4618 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
4619 if (RegRange) {
4620 // Remove last register operand because registers from register range
4621 // should be inserted first.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004622 if ((isGP64bit() && RegNo == Mips::RA_64) ||
4623 (!isGP64bit() && RegNo == Mips::RA)) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004624 Regs.push_back(RegNo);
4625 } else {
4626 unsigned TmpReg = PrevReg + 1;
4627 while (TmpReg <= RegNo) {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004628 if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) ||
4629 (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) &&
4630 isGP64bit())) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004631 Error(E, "invalid register operand");
4632 return MatchOperand_ParseFail;
4633 }
4634
4635 PrevReg = TmpReg;
4636 Regs.push_back(TmpReg++);
4637 }
4638 }
4639
4640 RegRange = false;
4641 } else {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004642 if ((PrevReg == Mips::NoRegister) &&
4643 ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) ||
4644 (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA)))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004645 Error(E, "$16 or $31 expected");
4646 return MatchOperand_ParseFail;
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004647 } else if (!(((RegNo == Mips::FP || RegNo == Mips::RA ||
4648 (RegNo >= Mips::S0 && RegNo <= Mips::S7)) &&
4649 !isGP64bit()) ||
4650 ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 ||
4651 (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) &&
4652 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004653 Error(E, "invalid register operand");
4654 return MatchOperand_ParseFail;
4655 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004656 ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) ||
4657 (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 &&
4658 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004659 Error(E, "consecutive register numbers expected");
4660 return MatchOperand_ParseFail;
4661 }
4662
4663 Regs.push_back(RegNo);
4664 }
4665
4666 if (Parser.getTok().is(AsmToken::Minus))
4667 RegRange = true;
4668
4669 if (!Parser.getTok().isNot(AsmToken::Minus) &&
4670 !Parser.getTok().isNot(AsmToken::Comma)) {
4671 Error(E, "',' or '-' expected");
4672 return MatchOperand_ParseFail;
4673 }
4674
4675 Lex(); // Consume comma or minus
4676 if (Parser.getTok().isNot(AsmToken::Dollar))
4677 break;
4678
4679 PrevReg = RegNo;
4680 }
4681
4682 SMLoc E = Parser.getTok().getLoc();
4683 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4684 parseMemOperand(Operands);
4685 return MatchOperand_Success;
4686}
4687
Zoran Jovanovic2deca342014-12-16 14:59:10 +00004688MipsAsmParser::OperandMatchResultTy
4689MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
4690 MCAsmParser &Parser = getParser();
4691
4692 SMLoc S = Parser.getTok().getLoc();
4693 if (parseAnyRegister(Operands) != MatchOperand_Success)
4694 return MatchOperand_ParseFail;
4695
4696 SMLoc E = Parser.getTok().getLoc();
4697 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
4698 unsigned Reg = Op.getGPR32Reg();
4699 Operands.pop_back();
4700 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
4701 return MatchOperand_Success;
4702}
4703
Zoran Jovanovic41688672015-02-10 16:36:20 +00004704MipsAsmParser::OperandMatchResultTy
4705MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
4706 MCAsmParser &Parser = getParser();
4707 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4708 SmallVector<unsigned, 10> Regs;
4709
4710 if (Parser.getTok().isNot(AsmToken::Dollar))
4711 return MatchOperand_ParseFail;
4712
4713 SMLoc S = Parser.getTok().getLoc();
4714
4715 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4716 return MatchOperand_ParseFail;
4717
4718 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4719 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4720 Regs.push_back(RegNo);
4721
4722 SMLoc E = Parser.getTok().getLoc();
4723 if (Parser.getTok().isNot(AsmToken::Comma)) {
4724 Error(E, "',' expected");
4725 return MatchOperand_ParseFail;
4726 }
4727
4728 // Remove comma.
4729 Parser.Lex();
4730
4731 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4732 return MatchOperand_ParseFail;
4733
4734 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4735 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4736 Regs.push_back(RegNo);
4737
4738 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4739
4740 return MatchOperand_Success;
4741}
4742
Jack Carterdc1e35d2012-09-06 20:00:02 +00004743MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
4744
Vladimir Medic4c299852013-11-06 11:27:05 +00004745 MCSymbolRefExpr::VariantKind VK =
4746 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
4747 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
4748 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
4749 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
4750 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
4751 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
4752 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
4753 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
4754 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
4755 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
4756 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
4757 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
4758 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
4759 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
4760 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
4761 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
4762 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
4763 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00004764 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
4765 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
4766 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
4767 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
4768 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
4769 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00004770 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
4771 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00004772 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00004773
Matheus Almeida2852af82014-04-22 10:15:54 +00004774 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00004775
Jack Carterdc1e35d2012-09-06 20:00:02 +00004776 return VK;
4777}
Jack Cartera63b16a2012-09-07 00:23:42 +00004778
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004779/// Sometimes (i.e. load/stores) the operand may be followed immediately by
4780/// either this.
4781/// ::= '(', register, ')'
4782/// handle it before we iterate so we don't get tripped up by the lack of
4783/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004784bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004785 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004786 if (getLexer().is(AsmToken::LParen)) {
4787 Operands.push_back(
4788 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
4789 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004790 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004791 SMLoc Loc = getLexer().getLoc();
4792 Parser.eatToEndOfStatement();
4793 return Error(Loc, "unexpected token in argument list");
4794 }
4795 if (Parser.getTok().isNot(AsmToken::RParen)) {
4796 SMLoc Loc = getLexer().getLoc();
4797 Parser.eatToEndOfStatement();
4798 return Error(Loc, "unexpected token, expected ')'");
4799 }
4800 Operands.push_back(
4801 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
4802 Parser.Lex();
4803 }
4804 return false;
4805}
4806
4807/// Sometimes (i.e. in MSA) the operand may be followed immediately by
4808/// either one of these.
4809/// ::= '[', register, ']'
4810/// ::= '[', integer, ']'
4811/// handle it before we iterate so we don't get tripped up by the lack of
4812/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004813bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00004814 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004815 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004816 if (getLexer().is(AsmToken::LBrac)) {
4817 Operands.push_back(
4818 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
4819 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004820 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004821 SMLoc Loc = getLexer().getLoc();
4822 Parser.eatToEndOfStatement();
4823 return Error(Loc, "unexpected token in argument list");
4824 }
4825 if (Parser.getTok().isNot(AsmToken::RBrac)) {
4826 SMLoc Loc = getLexer().getLoc();
4827 Parser.eatToEndOfStatement();
4828 return Error(Loc, "unexpected token, expected ']'");
4829 }
4830 Operands.push_back(
4831 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
4832 Parser.Lex();
4833 }
4834 return false;
4835}
4836
David Blaikie960ea3f2014-06-08 16:18:35 +00004837bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
4838 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004839 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004840 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004841
4842 // We have reached first instruction, module directive are now forbidden.
4843 getTargetStreamer().forbidModuleDirective();
4844
Vladimir Medic74593e62013-07-17 15:00:42 +00004845 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00004846 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00004847 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00004848 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00004849 }
Vladimir Medic64828a12013-07-16 10:07:14 +00004850 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004851 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004852
4853 // Read the remaining operands.
4854 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4855 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004856 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004857 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004858 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004859 return Error(Loc, "unexpected token in argument list");
4860 }
Toma Tabacu13964452014-09-04 13:23:44 +00004861 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004862 return true;
4863 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00004864
Jack Carterd0bd6422013-04-18 00:41:53 +00004865 while (getLexer().is(AsmToken::Comma)) {
4866 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00004867 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004868 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004869 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004870 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004871 return Error(Loc, "unexpected token in argument list");
4872 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004873 // Parse bracket and parenthesis suffixes before we iterate
4874 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00004875 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004876 return true;
4877 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00004878 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004879 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00004880 }
4881 }
Jack Carterb4dbc172012-09-05 23:34:03 +00004882 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4883 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004884 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004885 return Error(Loc, "unexpected token in argument list");
4886 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004887 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00004888 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00004889}
4890
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004891bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004892 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004893 SMLoc Loc = getLexer().getLoc();
4894 Parser.eatToEndOfStatement();
4895 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00004896}
4897
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004898bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004899 return Error(Loc, ErrorMsg);
4900}
4901
Jack Carter0b744b32012-10-04 02:29:46 +00004902bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004903 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004904 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00004905
4906 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00004907 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00004908
4909 Parser.Lex(); // Eat "noat".
4910
Jack Carterd0bd6422013-04-18 00:41:53 +00004911 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004912 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004913 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004914 return false;
4915 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004916
4917 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004918 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004919 return false;
4920}
Jack Carterd0bd6422013-04-18 00:41:53 +00004921
Jack Carter0b744b32012-10-04 02:29:46 +00004922bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00004923 // Line can be: ".set at", which sets $at to $1
4924 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00004925 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00004926 Parser.Lex(); // Eat "at".
4927
Jack Carter0b744b32012-10-04 02:29:46 +00004928 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004929 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00004930 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00004931
4932 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004933 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004934 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00004935 }
4936
4937 if (getLexer().isNot(AsmToken::Equal)) {
4938 reportParseError("unexpected token, expected equals sign");
4939 return false;
4940 }
4941 Parser.Lex(); // Eat "=".
4942
4943 if (getLexer().isNot(AsmToken::Dollar)) {
4944 if (getLexer().is(AsmToken::EndOfStatement)) {
4945 reportParseError("no register specified");
4946 return false;
4947 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00004948 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00004949 return false;
4950 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004951 }
4952 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00004953
Toma Tabacu16a74492015-02-13 10:30:57 +00004954 // Find out what "reg" is.
4955 unsigned AtRegNo;
4956 const AsmToken &Reg = Parser.getTok();
4957 if (Reg.is(AsmToken::Identifier)) {
4958 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
4959 } else if (Reg.is(AsmToken::Integer)) {
4960 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00004961 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00004962 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00004963 return false;
4964 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004965
4966 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00004967 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004968 reportParseError("invalid register");
4969 return false;
4970 }
4971 Parser.Lex(); // Eat "reg".
4972
4973 // If this is not the end of the statement, report an error.
4974 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4975 reportParseError("unexpected token, expected end of statement");
4976 return false;
4977 }
4978
4979 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
4980
4981 Parser.Lex(); // Consume the EndOfStatement.
4982 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004983}
4984
4985bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004986 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004987 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004988 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004989 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004990 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004991 return false;
4992 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004993 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00004994 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004995 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004996 return false;
4997}
4998
4999bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005000 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005001 Parser.Lex();
5002 // If this is not the end of the statement, report an error.
5003 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005004 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005005 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00005006 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005007 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00005008 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00005009 Parser.Lex(); // Consume the EndOfStatement.
5010 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005011}
5012
5013bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005014 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00005015 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00005016 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005017 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005018 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005019 return false;
5020 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005021 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00005022 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00005023 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005024 return false;
5025}
5026
5027bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005028 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00005029 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00005030 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005031 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005032 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005033 return false;
5034 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005035 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00005036 reportParseError("`noreorder' must be set before `nomacro'");
5037 return false;
5038 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005039 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00005040 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00005041 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005042 return false;
5043}
Jack Carterd76b2372013-03-21 21:44:16 +00005044
Daniel Sanders44934432014-08-07 12:03:36 +00005045bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005046 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00005047 Parser.Lex();
5048
5049 // If this is not the end of the statement, report an error.
5050 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005051 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00005052
5053 setFeatureBits(Mips::FeatureMSA, "msa");
5054 getTargetStreamer().emitDirectiveSetMsa();
5055 return false;
5056}
5057
5058bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005059 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00005060 Parser.Lex();
5061
5062 // If this is not the end of the statement, report an error.
5063 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005064 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00005065
5066 clearFeatureBits(Mips::FeatureMSA, "msa");
5067 getTargetStreamer().emitDirectiveSetNoMsa();
5068 return false;
5069}
5070
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005071bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005072 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005073 Parser.Lex(); // Eat "nodsp".
5074
5075 // If this is not the end of the statement, report an error.
5076 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5077 reportParseError("unexpected token, expected end of statement");
5078 return false;
5079 }
5080
5081 clearFeatureBits(Mips::FeatureDSP, "dsp");
5082 getTargetStreamer().emitDirectiveSetNoDsp();
5083 return false;
5084}
5085
Toma Tabacucc2502d2014-11-04 17:18:07 +00005086bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005087 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005088 Parser.Lex(); // Eat "mips16".
5089
Jack Carter39536722014-01-22 23:08:42 +00005090 // If this is not the end of the statement, report an error.
5091 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005092 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00005093 return false;
5094 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00005095
5096 setFeatureBits(Mips::FeatureMips16, "mips16");
5097 getTargetStreamer().emitDirectiveSetMips16();
5098 Parser.Lex(); // Consume the EndOfStatement.
5099 return false;
5100}
5101
5102bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005103 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005104 Parser.Lex(); // Eat "nomips16".
5105
5106 // If this is not the end of the statement, report an error.
5107 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5108 reportParseError("unexpected token, expected end of statement");
5109 return false;
5110 }
5111
5112 clearFeatureBits(Mips::FeatureMips16, "mips16");
5113 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00005114 Parser.Lex(); // Consume the EndOfStatement.
5115 return false;
5116}
5117
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005118bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005119 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005120 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005121 // Line can be: .set fp=32
5122 // .set fp=xx
5123 // .set fp=64
5124 Parser.Lex(); // Eat fp token
5125 AsmToken Tok = Parser.getTok();
5126 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005127 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005128 return false;
5129 }
5130 Parser.Lex(); // Eat '=' token.
5131 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005132
5133 if (!parseFpABIValue(FpAbiVal, ".set"))
5134 return false;
5135
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005136 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005137 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005138 return false;
5139 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005140 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005141 Parser.Lex(); // Consume the EndOfStatement.
5142 return false;
5143}
5144
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005145bool MipsAsmParser::parseSetOddSPRegDirective() {
5146 MCAsmParser &Parser = getParser();
5147
5148 Parser.Lex(); // Eat "oddspreg".
5149 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5150 reportParseError("unexpected token, expected end of statement");
5151 return false;
5152 }
5153
5154 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5155 getTargetStreamer().emitDirectiveSetOddSPReg();
5156 return false;
5157}
5158
5159bool MipsAsmParser::parseSetNoOddSPRegDirective() {
5160 MCAsmParser &Parser = getParser();
5161
5162 Parser.Lex(); // Eat "nooddspreg".
5163 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5164 reportParseError("unexpected token, expected end of statement");
5165 return false;
5166 }
5167
5168 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5169 getTargetStreamer().emitDirectiveSetNoOddSPReg();
5170 return false;
5171}
5172
Toma Tabacu9db22db2014-09-09 10:15:38 +00005173bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005174 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005175 SMLoc Loc = getLexer().getLoc();
5176
5177 Parser.Lex();
5178 if (getLexer().isNot(AsmToken::EndOfStatement))
5179 return reportParseError("unexpected token, expected end of statement");
5180
5181 // Always keep an element on the options "stack" to prevent the user
5182 // from changing the initial options. This is how we remember them.
5183 if (AssemblerOptions.size() == 2)
5184 return reportParseError(Loc, ".set pop with no .set push");
5185
Akira Hatanakab11ef082015-11-14 06:35:56 +00005186 MCSubtargetInfo &STI = copySTI();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005187 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005188 setAvailableFeatures(
5189 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
5190 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00005191
5192 getTargetStreamer().emitDirectiveSetPop();
5193 return false;
5194}
5195
5196bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005197 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005198 Parser.Lex();
5199 if (getLexer().isNot(AsmToken::EndOfStatement))
5200 return reportParseError("unexpected token, expected end of statement");
5201
5202 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00005203 AssemblerOptions.push_back(
5204 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00005205
5206 getTargetStreamer().emitDirectiveSetPush();
5207 return false;
5208}
5209
Toma Tabacu29696502015-06-02 09:48:04 +00005210bool MipsAsmParser::parseSetSoftFloatDirective() {
5211 MCAsmParser &Parser = getParser();
5212 Parser.Lex();
5213 if (getLexer().isNot(AsmToken::EndOfStatement))
5214 return reportParseError("unexpected token, expected end of statement");
5215
5216 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5217 getTargetStreamer().emitDirectiveSetSoftFloat();
5218 return false;
5219}
5220
5221bool MipsAsmParser::parseSetHardFloatDirective() {
5222 MCAsmParser &Parser = getParser();
5223 Parser.Lex();
5224 if (getLexer().isNot(AsmToken::EndOfStatement))
5225 return reportParseError("unexpected token, expected end of statement");
5226
5227 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5228 getTargetStreamer().emitDirectiveSetHardFloat();
5229 return false;
5230}
5231
Jack Carterd76b2372013-03-21 21:44:16 +00005232bool MipsAsmParser::parseSetAssignment() {
5233 StringRef Name;
5234 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00005235 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00005236
5237 if (Parser.parseIdentifier(Name))
5238 reportParseError("expected identifier after .set");
5239
5240 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005241 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00005242 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00005243
Jack Carter3b2c96e2014-01-22 23:31:38 +00005244 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00005245 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00005246
Jim Grosbach6f482002015-05-18 18:43:14 +00005247 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00005248 Sym->setVariableValue(Value);
5249
5250 return false;
5251}
Jack Carterd0bd6422013-04-18 00:41:53 +00005252
Toma Tabacu26647792014-09-09 12:52:14 +00005253bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005254 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00005255 Parser.Lex();
5256 if (getLexer().isNot(AsmToken::EndOfStatement))
5257 return reportParseError("unexpected token, expected end of statement");
5258
5259 // Reset assembler options to their initial values.
Akira Hatanakab11ef082015-11-14 06:35:56 +00005260 MCSubtargetInfo &STI = copySTI();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005261 setAvailableFeatures(
5262 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
5263 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00005264 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
5265
5266 getTargetStreamer().emitDirectiveSetMips0();
5267 return false;
5268}
5269
Toma Tabacu85618b32014-08-19 14:22:52 +00005270bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005271 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00005272 Parser.Lex();
5273 if (getLexer().isNot(AsmToken::Equal))
5274 return reportParseError("unexpected token, expected equals sign");
5275
5276 Parser.Lex();
5277 StringRef Arch;
5278 if (Parser.parseIdentifier(Arch))
5279 return reportParseError("expected arch identifier");
5280
5281 StringRef ArchFeatureName =
5282 StringSwitch<StringRef>(Arch)
5283 .Case("mips1", "mips1")
5284 .Case("mips2", "mips2")
5285 .Case("mips3", "mips3")
5286 .Case("mips4", "mips4")
5287 .Case("mips5", "mips5")
5288 .Case("mips32", "mips32")
5289 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005290 .Case("mips32r3", "mips32r3")
5291 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005292 .Case("mips32r6", "mips32r6")
5293 .Case("mips64", "mips64")
5294 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005295 .Case("mips64r3", "mips64r3")
5296 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005297 .Case("mips64r6", "mips64r6")
5298 .Case("cnmips", "cnmips")
5299 .Case("r4000", "mips3") // This is an implementation of Mips3.
5300 .Default("");
5301
5302 if (ArchFeatureName.empty())
5303 return reportParseError("unsupported architecture");
5304
5305 selectArch(ArchFeatureName);
5306 getTargetStreamer().emitDirectiveSetArch(Arch);
5307 return false;
5308}
5309
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005310bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005311 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005312 Parser.Lex();
5313 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005314 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005315
Matheus Almeida2852af82014-04-22 10:15:54 +00005316 switch (Feature) {
5317 default:
5318 llvm_unreachable("Unimplemented feature");
5319 case Mips::FeatureDSP:
5320 setFeatureBits(Mips::FeatureDSP, "dsp");
5321 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005322 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005323 case Mips::FeatureMicroMips:
5324 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005325 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005326 case Mips::FeatureMips1:
5327 selectArch("mips1");
5328 getTargetStreamer().emitDirectiveSetMips1();
5329 break;
5330 case Mips::FeatureMips2:
5331 selectArch("mips2");
5332 getTargetStreamer().emitDirectiveSetMips2();
5333 break;
5334 case Mips::FeatureMips3:
5335 selectArch("mips3");
5336 getTargetStreamer().emitDirectiveSetMips3();
5337 break;
5338 case Mips::FeatureMips4:
5339 selectArch("mips4");
5340 getTargetStreamer().emitDirectiveSetMips4();
5341 break;
5342 case Mips::FeatureMips5:
5343 selectArch("mips5");
5344 getTargetStreamer().emitDirectiveSetMips5();
5345 break;
5346 case Mips::FeatureMips32:
5347 selectArch("mips32");
5348 getTargetStreamer().emitDirectiveSetMips32();
5349 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005350 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005351 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005352 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005353 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005354 case Mips::FeatureMips32r3:
5355 selectArch("mips32r3");
5356 getTargetStreamer().emitDirectiveSetMips32R3();
5357 break;
5358 case Mips::FeatureMips32r5:
5359 selectArch("mips32r5");
5360 getTargetStreamer().emitDirectiveSetMips32R5();
5361 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005362 case Mips::FeatureMips32r6:
5363 selectArch("mips32r6");
5364 getTargetStreamer().emitDirectiveSetMips32R6();
5365 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005366 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005367 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00005368 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005369 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005370 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005371 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005372 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005373 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005374 case Mips::FeatureMips64r3:
5375 selectArch("mips64r3");
5376 getTargetStreamer().emitDirectiveSetMips64R3();
5377 break;
5378 case Mips::FeatureMips64r5:
5379 selectArch("mips64r5");
5380 getTargetStreamer().emitDirectiveSetMips64R5();
5381 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005382 case Mips::FeatureMips64r6:
5383 selectArch("mips64r6");
5384 getTargetStreamer().emitDirectiveSetMips64R6();
5385 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005386 }
5387 return false;
5388}
5389
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005390bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005391 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005392 if (getLexer().isNot(AsmToken::Comma)) {
5393 SMLoc Loc = getLexer().getLoc();
5394 Parser.eatToEndOfStatement();
5395 return Error(Loc, ErrorStr);
5396 }
5397
Matheus Almeida2852af82014-04-22 10:15:54 +00005398 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005399 return true;
5400}
5401
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005402// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
5403// In this class, it is only used for .cprestore.
5404// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
5405// MipsTargetELFStreamer and MipsAsmParser.
5406bool MipsAsmParser::isPicAndNotNxxAbi() {
5407 return inPicMode() && !(isABI_N32() || isABI_N64());
5408}
5409
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005410bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00005411 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00005412 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005413
Toma Tabacudde4c462014-11-06 10:02:45 +00005414 if (inMips16Mode()) {
5415 reportParseError(".cpload is not supported in Mips16 mode");
5416 return false;
5417 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005418
David Blaikie960ea3f2014-06-08 16:18:35 +00005419 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00005420 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005421 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5422 reportParseError("expected register containing function address");
5423 return false;
5424 }
5425
David Blaikie960ea3f2014-06-08 16:18:35 +00005426 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
5427 if (!RegOpnd.isGPRAsmReg()) {
5428 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005429 return false;
5430 }
5431
Toma Tabacudde4c462014-11-06 10:02:45 +00005432 // If this is not the end of the statement, report an error.
5433 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5434 reportParseError("unexpected token, expected end of statement");
5435 return false;
5436 }
5437
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005438 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005439 return false;
5440}
5441
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005442bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
5443 MCAsmParser &Parser = getParser();
5444
5445 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
5446 // is used in non-PIC mode.
5447
5448 if (inMips16Mode()) {
5449 reportParseError(".cprestore is not supported in Mips16 mode");
5450 return false;
5451 }
5452
5453 // Get the stack offset value.
5454 const MCExpr *StackOffset;
5455 int64_t StackOffsetVal;
5456 if (Parser.parseExpression(StackOffset)) {
5457 reportParseError("expected stack offset value");
5458 return false;
5459 }
5460
5461 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
5462 reportParseError("stack offset is not an absolute expression");
5463 return false;
5464 }
5465
5466 if (StackOffsetVal < 0) {
5467 Warning(Loc, ".cprestore with negative stack offset has no effect");
5468 IsCpRestoreSet = false;
5469 } else {
5470 IsCpRestoreSet = true;
5471 CpRestoreOffset = StackOffsetVal;
5472 }
5473
5474 // If this is not the end of the statement, report an error.
5475 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5476 reportParseError("unexpected token, expected end of statement");
5477 return false;
5478 }
5479
5480 // Store the $gp on the stack.
5481 SmallVector<MCInst, 3> StoreInsts;
5482 createCpRestoreMemOp(false /*IsLoad*/, CpRestoreOffset /*StackOffset*/, Loc,
5483 StoreInsts);
5484
5485 getTargetStreamer().emitDirectiveCpRestore(StoreInsts, CpRestoreOffset);
5486 Parser.Lex(); // Consume the EndOfStatement.
5487 return false;
5488}
5489
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005490bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005491 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005492 unsigned FuncReg;
5493 unsigned Save;
5494 bool SaveIsReg = true;
5495
Matheus Almeida7e815762014-06-18 13:08:59 +00005496 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005497 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005498 if (ResTy == MatchOperand_NoMatch) {
5499 reportParseError("expected register containing function address");
5500 Parser.eatToEndOfStatement();
5501 return false;
5502 }
5503
5504 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5505 if (!FuncRegOpnd.isGPRAsmReg()) {
5506 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
5507 Parser.eatToEndOfStatement();
5508 return false;
5509 }
5510
5511 FuncReg = FuncRegOpnd.getGPR32Reg();
5512 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005513
Toma Tabacu65f10572014-09-16 15:00:52 +00005514 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005515 return true;
5516
Toma Tabacu13964452014-09-04 13:23:44 +00005517 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005518 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00005519 const MCExpr *OffsetExpr;
5520 int64_t OffsetVal;
5521 SMLoc ExprLoc = getLexer().getLoc();
5522
5523 if (Parser.parseExpression(OffsetExpr) ||
5524 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
5525 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00005526 Parser.eatToEndOfStatement();
5527 return false;
5528 }
Daniel Sanders5d796282015-09-21 09:26:55 +00005529
5530 Save = OffsetVal;
5531 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00005532 } else {
5533 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5534 if (!SaveOpnd.isGPRAsmReg()) {
5535 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
5536 Parser.eatToEndOfStatement();
5537 return false;
5538 }
5539 Save = SaveOpnd.getGPR32Reg();
5540 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005541
Toma Tabacu65f10572014-09-16 15:00:52 +00005542 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005543 return true;
5544
Toma Tabacu8874eac2015-02-18 13:46:53 +00005545 const MCExpr *Expr;
5546 if (Parser.parseExpression(Expr)) {
5547 reportParseError("expected expression");
5548 return false;
5549 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005550
Toma Tabacu8874eac2015-02-18 13:46:53 +00005551 if (Expr->getKind() != MCExpr::SymbolRef) {
5552 reportParseError("expected symbol");
5553 return false;
5554 }
5555 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
5556
Daniel Sandersf173dda2015-09-22 10:50:09 +00005557 CpSaveLocation = Save;
5558 CpSaveLocationIsRegister = SaveIsReg;
5559
Toma Tabacu8874eac2015-02-18 13:46:53 +00005560 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
5561 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005562 return false;
5563}
5564
Daniel Sandersf173dda2015-09-22 10:50:09 +00005565bool MipsAsmParser::parseDirectiveCPReturn() {
5566 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
5567 CpSaveLocationIsRegister);
5568 return false;
5569}
5570
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005571bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005572 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005573 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5574 const AsmToken &Tok = Parser.getTok();
5575
5576 if (Tok.getString() == "2008") {
5577 Parser.Lex();
5578 getTargetStreamer().emitDirectiveNaN2008();
5579 return false;
5580 } else if (Tok.getString() == "legacy") {
5581 Parser.Lex();
5582 getTargetStreamer().emitDirectiveNaNLegacy();
5583 return false;
5584 }
5585 }
5586 // If we don't recognize the option passed to the .nan
5587 // directive (e.g. no option or unknown option), emit an error.
5588 reportParseError("invalid option in .nan directive");
5589 return false;
5590}
5591
Jack Carter0b744b32012-10-04 02:29:46 +00005592bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005593 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005594 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00005595 const AsmToken &Tok = Parser.getTok();
5596
5597 if (Tok.getString() == "noat") {
5598 return parseSetNoAtDirective();
5599 } else if (Tok.getString() == "at") {
5600 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00005601 } else if (Tok.getString() == "arch") {
5602 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005603 } else if (Tok.getString() == "fp") {
5604 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005605 } else if (Tok.getString() == "oddspreg") {
5606 return parseSetOddSPRegDirective();
5607 } else if (Tok.getString() == "nooddspreg") {
5608 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005609 } else if (Tok.getString() == "pop") {
5610 return parseSetPopDirective();
5611 } else if (Tok.getString() == "push") {
5612 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00005613 } else if (Tok.getString() == "reorder") {
5614 return parseSetReorderDirective();
5615 } else if (Tok.getString() == "noreorder") {
5616 return parseSetNoReorderDirective();
5617 } else if (Tok.getString() == "macro") {
5618 return parseSetMacroDirective();
5619 } else if (Tok.getString() == "nomacro") {
5620 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00005621 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00005622 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005623 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00005624 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005625 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00005626 getTargetStreamer().emitDirectiveSetNoMicroMips();
5627 Parser.eatToEndOfStatement();
5628 return false;
5629 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005630 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00005631 } else if (Tok.getString() == "mips0") {
5632 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00005633 } else if (Tok.getString() == "mips1") {
5634 return parseSetFeature(Mips::FeatureMips1);
5635 } else if (Tok.getString() == "mips2") {
5636 return parseSetFeature(Mips::FeatureMips2);
5637 } else if (Tok.getString() == "mips3") {
5638 return parseSetFeature(Mips::FeatureMips3);
5639 } else if (Tok.getString() == "mips4") {
5640 return parseSetFeature(Mips::FeatureMips4);
5641 } else if (Tok.getString() == "mips5") {
5642 return parseSetFeature(Mips::FeatureMips5);
5643 } else if (Tok.getString() == "mips32") {
5644 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00005645 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005646 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005647 } else if (Tok.getString() == "mips32r3") {
5648 return parseSetFeature(Mips::FeatureMips32r3);
5649 } else if (Tok.getString() == "mips32r5") {
5650 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005651 } else if (Tok.getString() == "mips32r6") {
5652 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005653 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005654 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005655 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005656 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005657 } else if (Tok.getString() == "mips64r3") {
5658 return parseSetFeature(Mips::FeatureMips64r3);
5659 } else if (Tok.getString() == "mips64r5") {
5660 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005661 } else if (Tok.getString() == "mips64r6") {
5662 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00005663 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005664 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005665 } else if (Tok.getString() == "nodsp") {
5666 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00005667 } else if (Tok.getString() == "msa") {
5668 return parseSetMsaDirective();
5669 } else if (Tok.getString() == "nomsa") {
5670 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00005671 } else if (Tok.getString() == "softfloat") {
5672 return parseSetSoftFloatDirective();
5673 } else if (Tok.getString() == "hardfloat") {
5674 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00005675 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00005676 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00005677 parseSetAssignment();
5678 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005679 }
Jack Carter07c818d2013-01-25 01:31:34 +00005680
Jack Carter0b744b32012-10-04 02:29:46 +00005681 return true;
5682}
5683
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005684/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00005685/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005686bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005687 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005688 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5689 for (;;) {
5690 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005691 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00005692 return true;
5693
5694 getParser().getStreamer().EmitValue(Value, Size);
5695
5696 if (getLexer().is(AsmToken::EndOfStatement))
5697 break;
5698
Jack Carter07c818d2013-01-25 01:31:34 +00005699 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005700 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00005701 Parser.Lex();
5702 }
5703 }
5704
5705 Parser.Lex();
5706 return false;
5707}
5708
Vladimir Medic4c299852013-11-06 11:27:05 +00005709/// parseDirectiveGpWord
5710/// ::= .gpword local_sym
5711bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005712 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00005713 const MCExpr *Value;
5714 // EmitGPRel32Value requires an expression, so we are using base class
5715 // method to evaluate the expression.
5716 if (getParser().parseExpression(Value))
5717 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00005718 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00005719
Vladimir Medice10c1122013-11-13 13:18:04 +00005720 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005721 return Error(getLexer().getLoc(),
5722 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00005723 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00005724 return false;
5725}
5726
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005727/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00005728/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005729bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005730 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005731 const MCExpr *Value;
5732 // EmitGPRel64Value requires an expression, so we are using base class
5733 // method to evaluate the expression.
5734 if (getParser().parseExpression(Value))
5735 return true;
5736 getParser().getStreamer().EmitGPRel64Value(Value);
5737
5738 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005739 return Error(getLexer().getLoc(),
5740 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00005741 Parser.Lex(); // Eat EndOfStatement token.
5742 return false;
5743}
5744
Jack Carter0cd3c192014-01-06 23:27:31 +00005745bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005746 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00005747 // Get the option token.
5748 AsmToken Tok = Parser.getTok();
5749 // At the moment only identifiers are supported.
5750 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005751 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00005752 Parser.eatToEndOfStatement();
5753 return false;
5754 }
5755
5756 StringRef Option = Tok.getIdentifier();
5757
5758 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005759 // MipsAsmParser needs to know if the current PIC mode changes.
5760 IsPicEnabled = false;
5761
Jack Carter0cd3c192014-01-06 23:27:31 +00005762 getTargetStreamer().emitDirectiveOptionPic0();
5763 Parser.Lex();
5764 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5765 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005766 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005767 Parser.eatToEndOfStatement();
5768 }
5769 return false;
5770 }
5771
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005772 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005773 // MipsAsmParser needs to know if the current PIC mode changes.
5774 IsPicEnabled = true;
5775
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005776 getTargetStreamer().emitDirectiveOptionPic2();
5777 Parser.Lex();
5778 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5779 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005780 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005781 Parser.eatToEndOfStatement();
5782 }
5783 return false;
5784 }
5785
Jack Carter0cd3c192014-01-06 23:27:31 +00005786 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00005787 Warning(Parser.getTok().getLoc(),
5788 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00005789 Parser.eatToEndOfStatement();
5790 return false;
5791}
5792
Toma Tabacu9ca50962015-04-16 09:53:47 +00005793/// parseInsnDirective
5794/// ::= .insn
5795bool MipsAsmParser::parseInsnDirective() {
5796 // If this is not the end of the statement, report an error.
5797 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5798 reportParseError("unexpected token, expected end of statement");
5799 return false;
5800 }
5801
5802 // The actual label marking happens in
5803 // MipsELFStreamer::createPendingLabelRelocs().
5804 getTargetStreamer().emitDirectiveInsn();
5805
5806 getParser().Lex(); // Eat EndOfStatement token.
5807 return false;
5808}
5809
Simon Atanasyanbe186202016-02-11 06:45:54 +00005810/// parseSSectionDirective
5811/// ::= .sbss
5812/// ::= .sdata
5813bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) {
5814 // If this is not the end of the statement, report an error.
5815 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5816 reportParseError("unexpected token, expected end of statement");
5817 return false;
5818 }
5819
5820 MCSection *ELFSection = getContext().getELFSection(
5821 Section, Type, ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL);
5822 getParser().getStreamer().SwitchSection(ELFSection);
5823
5824 getParser().Lex(); // Eat EndOfStatement token.
5825 return false;
5826}
5827
Daniel Sanders7e527422014-07-10 13:38:23 +00005828/// parseDirectiveModule
5829/// ::= .module oddspreg
5830/// ::= .module nooddspreg
5831/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00005832/// ::= .module softfloat
5833/// ::= .module hardfloat
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005834bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005835 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005836 MCAsmLexer &Lexer = getLexer();
5837 SMLoc L = Lexer.getLoc();
5838
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00005839 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005840 // TODO : get a better message.
5841 reportParseError(".module directive must appear before any code");
5842 return false;
5843 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005844
Toma Tabacuc405c822015-01-23 10:40:19 +00005845 StringRef Option;
5846 if (Parser.parseIdentifier(Option)) {
5847 reportParseError("expected .module option identifier");
5848 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005849 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005850
Toma Tabacuc405c822015-01-23 10:40:19 +00005851 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005852 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005853
Toma Tabacu3c499582015-06-25 10:56:57 +00005854 // Synchronize the abiflags information with the FeatureBits information we
5855 // changed above.
5856 getTargetStreamer().updateABIInfo(*this);
5857
5858 // If printing assembly, use the recently updated abiflags information.
5859 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5860 // emitted at the end).
5861 getTargetStreamer().emitDirectiveModuleOddSPReg();
5862
Toma Tabacuc405c822015-01-23 10:40:19 +00005863 // If this is not the end of the statement, report an error.
5864 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5865 reportParseError("unexpected token, expected end of statement");
5866 return false;
5867 }
5868
5869 return false; // parseDirectiveModule has finished successfully.
5870 } else if (Option == "nooddspreg") {
5871 if (!isABI_O32()) {
5872 Error(L, "'.module nooddspreg' requires the O32 ABI");
5873 return false;
5874 }
5875
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005876 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005877
Toma Tabacu3c499582015-06-25 10:56:57 +00005878 // Synchronize the abiflags information with the FeatureBits information we
5879 // changed above.
5880 getTargetStreamer().updateABIInfo(*this);
5881
5882 // If printing assembly, use the recently updated abiflags information.
5883 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5884 // emitted at the end).
5885 getTargetStreamer().emitDirectiveModuleOddSPReg();
5886
Toma Tabacuc405c822015-01-23 10:40:19 +00005887 // If this is not the end of the statement, report an error.
5888 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5889 reportParseError("unexpected token, expected end of statement");
5890 return false;
5891 }
5892
5893 return false; // parseDirectiveModule has finished successfully.
5894 } else if (Option == "fp") {
5895 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00005896 } else if (Option == "softfloat") {
5897 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5898
5899 // Synchronize the ABI Flags information with the FeatureBits information we
5900 // updated above.
5901 getTargetStreamer().updateABIInfo(*this);
5902
5903 // If printing assembly, use the recently updated ABI Flags information.
5904 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5905 // emitted later).
5906 getTargetStreamer().emitDirectiveModuleSoftFloat();
5907
5908 // If this is not the end of the statement, report an error.
5909 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5910 reportParseError("unexpected token, expected end of statement");
5911 return false;
5912 }
5913
5914 return false; // parseDirectiveModule has finished successfully.
5915 } else if (Option == "hardfloat") {
5916 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5917
5918 // Synchronize the ABI Flags information with the FeatureBits information we
5919 // updated above.
5920 getTargetStreamer().updateABIInfo(*this);
5921
5922 // If printing assembly, use the recently updated ABI Flags information.
5923 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5924 // emitted later).
5925 getTargetStreamer().emitDirectiveModuleHardFloat();
5926
5927 // If this is not the end of the statement, report an error.
5928 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5929 reportParseError("unexpected token, expected end of statement");
5930 return false;
5931 }
5932
5933 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00005934 } else {
5935 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
5936 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005937}
5938
5939/// parseDirectiveModuleFP
5940/// ::= =32
5941/// ::= =xx
5942/// ::= =64
5943bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005944 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005945 MCAsmLexer &Lexer = getLexer();
5946
5947 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005948 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005949 return false;
5950 }
5951 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005952
Daniel Sanders7e527422014-07-10 13:38:23 +00005953 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005954 if (!parseFpABIValue(FpABI, ".module"))
5955 return false;
5956
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005957 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005958 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005959 return false;
5960 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005961
Toma Tabacua64e5402015-06-25 12:44:38 +00005962 // Synchronize the abiflags information with the FeatureBits information we
5963 // changed above.
5964 getTargetStreamer().updateABIInfo(*this);
5965
5966 // If printing assembly, use the recently updated abiflags information.
5967 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5968 // emitted at the end).
5969 getTargetStreamer().emitDirectiveModuleFP();
5970
Daniel Sanders7e527422014-07-10 13:38:23 +00005971 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005972 return false;
5973}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005974
Daniel Sanders7e527422014-07-10 13:38:23 +00005975bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005976 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005977 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005978 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005979 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005980
5981 if (Lexer.is(AsmToken::Identifier)) {
5982 StringRef Value = Parser.getTok().getString();
5983 Parser.Lex();
5984
5985 if (Value != "xx") {
5986 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5987 return false;
5988 }
5989
5990 if (!isABI_O32()) {
5991 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
5992 return false;
5993 }
5994
Daniel Sanders7e527422014-07-10 13:38:23 +00005995 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005996 if (ModuleLevelOptions) {
5997 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5998 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5999 } else {
6000 setFeatureBits(Mips::FeatureFPXX, "fpxx");
6001 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
6002 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006003 return true;
6004 }
6005
6006 if (Lexer.is(AsmToken::Integer)) {
6007 unsigned Value = Parser.getTok().getIntVal();
6008 Parser.Lex();
6009
6010 if (Value != 32 && Value != 64) {
6011 reportParseError("unsupported value, expected 'xx', '32' or '64'");
6012 return false;
6013 }
6014
6015 if (Value == 32) {
6016 if (!isABI_O32()) {
6017 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
6018 return false;
6019 }
6020
Daniel Sanders7e527422014-07-10 13:38:23 +00006021 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006022 if (ModuleLevelOptions) {
6023 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6024 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6025 } else {
6026 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
6027 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
6028 }
Toma Tabacua64e5402015-06-25 12:44:38 +00006029 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00006030 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006031 if (ModuleLevelOptions) {
6032 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6033 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6034 } else {
6035 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
6036 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
6037 }
Toma Tabacua64e5402015-06-25 12:44:38 +00006038 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006039
Daniel Sanders7e527422014-07-10 13:38:23 +00006040 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006041 }
6042
6043 return false;
6044}
6045
Jack Carter0b744b32012-10-04 02:29:46 +00006046bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006047 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00006048 StringRef IDVal = DirectiveID.getString();
6049
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006050 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00006051 return parseDirectiveCpLoad(DirectiveID.getLoc());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006052 if (IDVal == ".cprestore")
6053 return parseDirectiveCpRestore(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00006054 if (IDVal == ".dword") {
6055 parseDataDirective(8, DirectiveID.getLoc());
6056 return false;
6057 }
Jack Carterd0bd6422013-04-18 00:41:53 +00006058 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006059 StringRef SymbolName;
6060
6061 if (Parser.parseIdentifier(SymbolName)) {
6062 reportParseError("expected identifier after .ent");
6063 return false;
6064 }
6065
6066 // There's an undocumented extension that allows an integer to
6067 // follow the name of the procedure which AFAICS is ignored by GAS.
6068 // Example: .ent foo,2
6069 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6070 if (getLexer().isNot(AsmToken::Comma)) {
6071 // Even though we accept this undocumented extension for compatibility
6072 // reasons, the additional integer argument does not actually change
6073 // the behaviour of the '.ent' directive, so we would like to discourage
6074 // its use. We do this by not referring to the extended version in
6075 // error messages which are not directly related to its use.
6076 reportParseError("unexpected token, expected end of statement");
6077 return false;
6078 }
6079 Parser.Lex(); // Eat the comma.
6080 const MCExpr *DummyNumber;
6081 int64_t DummyNumberVal;
6082 // If the user was explicitly trying to use the extended version,
6083 // we still give helpful extension-related error messages.
6084 if (Parser.parseExpression(DummyNumber)) {
6085 reportParseError("expected number after comma");
6086 return false;
6087 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00006088 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006089 reportParseError("expected an absolute expression after comma");
6090 return false;
6091 }
6092 }
6093
6094 // If this is not the end of the statement, report an error.
6095 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6096 reportParseError("unexpected token, expected end of statement");
6097 return false;
6098 }
6099
Jim Grosbach6f482002015-05-18 18:43:14 +00006100 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006101
6102 getTargetStreamer().emitDirectiveEnt(*Sym);
6103 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006104 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006105 return false;
6106 }
6107
Jack Carter07c818d2013-01-25 01:31:34 +00006108 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006109 StringRef SymbolName;
6110
6111 if (Parser.parseIdentifier(SymbolName)) {
6112 reportParseError("expected identifier after .end");
6113 return false;
6114 }
6115
6116 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6117 reportParseError("unexpected token, expected end of statement");
6118 return false;
6119 }
6120
6121 if (CurrentFn == nullptr) {
6122 reportParseError(".end used without .ent");
6123 return false;
6124 }
6125
6126 if ((SymbolName != CurrentFn->getName())) {
6127 reportParseError(".end symbol does not match .ent symbol");
6128 return false;
6129 }
6130
6131 getTargetStreamer().emitDirectiveEnd(SymbolName);
6132 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006133 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006134 return false;
6135 }
6136
Jack Carter07c818d2013-01-25 01:31:34 +00006137 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006138 // .frame $stack_reg, frame_size_in_bytes, $return_reg
6139 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00006140 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006141 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6142 reportParseError("expected stack register");
6143 return false;
6144 }
6145
6146 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6147 if (!StackRegOpnd.isGPRAsmReg()) {
6148 reportParseError(StackRegOpnd.getStartLoc(),
6149 "expected general purpose register");
6150 return false;
6151 }
6152 unsigned StackReg = StackRegOpnd.getGPR32Reg();
6153
6154 if (Parser.getTok().is(AsmToken::Comma))
6155 Parser.Lex();
6156 else {
6157 reportParseError("unexpected token, expected comma");
6158 return false;
6159 }
6160
6161 // Parse the frame size.
6162 const MCExpr *FrameSize;
6163 int64_t FrameSizeVal;
6164
6165 if (Parser.parseExpression(FrameSize)) {
6166 reportParseError("expected frame size value");
6167 return false;
6168 }
6169
Jim Grosbach13760bd2015-05-30 01:25:56 +00006170 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006171 reportParseError("frame size not an absolute expression");
6172 return false;
6173 }
6174
6175 if (Parser.getTok().is(AsmToken::Comma))
6176 Parser.Lex();
6177 else {
6178 reportParseError("unexpected token, expected comma");
6179 return false;
6180 }
6181
6182 // Parse the return register.
6183 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00006184 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006185 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6186 reportParseError("expected return register");
6187 return false;
6188 }
6189
6190 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6191 if (!ReturnRegOpnd.isGPRAsmReg()) {
6192 reportParseError(ReturnRegOpnd.getStartLoc(),
6193 "expected general purpose register");
6194 return false;
6195 }
6196
6197 // If this is not the end of the statement, report an error.
6198 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6199 reportParseError("unexpected token, expected end of statement");
6200 return false;
6201 }
6202
6203 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
6204 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006205 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006206 return false;
6207 }
6208
Jack Carter07c818d2013-01-25 01:31:34 +00006209 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00006210 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00006211 }
6212
Daniel Sandersd97a6342014-08-13 10:07:34 +00006213 if (IDVal == ".mask" || IDVal == ".fmask") {
6214 // .mask bitmask, frame_offset
6215 // bitmask: One bit for each register used.
6216 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
6217 // first register is expected to be saved.
6218 // Examples:
6219 // .mask 0x80000000, -4
6220 // .fmask 0x80000000, -4
6221 //
Jack Carterbe332172012-09-07 00:48:02 +00006222
Daniel Sandersd97a6342014-08-13 10:07:34 +00006223 // Parse the bitmask
6224 const MCExpr *BitMask;
6225 int64_t BitMaskVal;
6226
6227 if (Parser.parseExpression(BitMask)) {
6228 reportParseError("expected bitmask value");
6229 return false;
6230 }
6231
Jim Grosbach13760bd2015-05-30 01:25:56 +00006232 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006233 reportParseError("bitmask not an absolute expression");
6234 return false;
6235 }
6236
6237 if (Parser.getTok().is(AsmToken::Comma))
6238 Parser.Lex();
6239 else {
6240 reportParseError("unexpected token, expected comma");
6241 return false;
6242 }
6243
6244 // Parse the frame_offset
6245 const MCExpr *FrameOffset;
6246 int64_t FrameOffsetVal;
6247
6248 if (Parser.parseExpression(FrameOffset)) {
6249 reportParseError("expected frame offset value");
6250 return false;
6251 }
6252
Jim Grosbach13760bd2015-05-30 01:25:56 +00006253 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006254 reportParseError("frame offset not an absolute expression");
6255 return false;
6256 }
6257
6258 // If this is not the end of the statement, report an error.
6259 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6260 reportParseError("unexpected token, expected end of statement");
6261 return false;
6262 }
6263
6264 if (IDVal == ".mask")
6265 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
6266 else
6267 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00006268 return false;
6269 }
6270
Matheus Almeida0051f2d2014-04-16 15:48:55 +00006271 if (IDVal == ".nan")
6272 return parseDirectiveNaN();
6273
Jack Carter07c818d2013-01-25 01:31:34 +00006274 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00006275 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00006276 return false;
6277 }
6278
Rafael Espindolab59fb732014-03-28 18:50:26 +00006279 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00006280 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00006281 return false;
6282 }
6283
Jack Carter07c818d2013-01-25 01:31:34 +00006284 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00006285 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00006286 return false;
6287 }
6288
Scott Egertond1aeb052016-02-15 16:11:51 +00006289 if (IDVal == ".hword") {
6290 parseDataDirective(2, DirectiveID.getLoc());
6291 return false;
6292 }
6293
Jack Carter0cd3c192014-01-06 23:27:31 +00006294 if (IDVal == ".option")
6295 return parseDirectiveOption();
6296
6297 if (IDVal == ".abicalls") {
6298 getTargetStreamer().emitDirectiveAbiCalls();
6299 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006300 Error(Parser.getTok().getLoc(),
6301 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00006302 // Clear line
6303 Parser.eatToEndOfStatement();
6304 }
6305 return false;
6306 }
6307
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006308 if (IDVal == ".cpsetup")
6309 return parseDirectiveCPSetup();
6310
Daniel Sandersf173dda2015-09-22 10:50:09 +00006311 if (IDVal == ".cpreturn")
6312 return parseDirectiveCPReturn();
6313
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006314 if (IDVal == ".module")
6315 return parseDirectiveModule();
6316
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00006317 if (IDVal == ".llvm_internal_mips_reallow_module_directive")
6318 return parseInternalDirectiveReallowModule();
6319
Toma Tabacu9ca50962015-04-16 09:53:47 +00006320 if (IDVal == ".insn")
6321 return parseInsnDirective();
6322
Simon Atanasyanbe186202016-02-11 06:45:54 +00006323 if (IDVal == ".sbss")
6324 return parseSSectionDirective(IDVal, ELF::SHT_NOBITS);
6325 if (IDVal == ".sdata")
6326 return parseSSectionDirective(IDVal, ELF::SHT_PROGBITS);
6327
Rafael Espindola870c4e92012-01-11 03:56:41 +00006328 return true;
6329}
6330
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00006331bool MipsAsmParser::parseInternalDirectiveReallowModule() {
6332 // If this is not the end of the statement, report an error.
6333 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6334 reportParseError("unexpected token, expected end of statement");
6335 return false;
6336 }
6337
6338 getTargetStreamer().reallowModuleDirective();
6339
6340 getParser().Lex(); // Eat EndOfStatement token.
6341 return false;
6342}
6343
Rafael Espindola870c4e92012-01-11 03:56:41 +00006344extern "C" void LLVMInitializeMipsAsmParser() {
6345 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
6346 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
6347 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
6348 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
6349}
Jack Carterb4dbc172012-09-05 23:34:03 +00006350
6351#define GET_REGISTER_MATCHER
6352#define GET_MATCHER_IMPLEMENTATION
6353#include "MipsGenAsmMatcher.inc"