blob: 86521de614c61b3ee5319c7272a848fa3b5de7e0 [file] [log] [blame]
Jia Liu9f610112012-02-17 08:55:11 +00001//===-- MipsAsmParser.cpp - Parse Mips assembly to MCInst instructions ----===//
Rafael Espindola870c4e92012-01-11 03:56:41 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Eric Christophera5762812015-01-26 17:33:46 +000010#include "MCTargetDesc/MipsABIInfo.h"
Petar Jovanovica5da5882014-02-04 18:41:57 +000011#include "MCTargetDesc/MipsMCExpr.h"
Rafael Espindola870c4e92012-01-11 03:56:41 +000012#include "MCTargetDesc/MipsMCTargetDesc.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000013#include "MipsRegisterInfo.h"
Daniel Sandersa6994442015-08-18 12:33:54 +000014#include "MipsTargetObjectFile.h"
Rafael Espindolaa17151a2013-10-08 13:08:17 +000015#include "MipsTargetStreamer.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000016#include "llvm/ADT/APInt.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000017#include "llvm/ADT/SmallVector.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000018#include "llvm/ADT/StringSwitch.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000019#include "llvm/MC/MCContext.h"
20#include "llvm/MC/MCExpr.h"
21#include "llvm/MC/MCInst.h"
Daniel Sandersa771fef2014-03-24 14:05:39 +000022#include "llvm/MC/MCInstBuilder.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000023#include "llvm/MC/MCParser/MCAsmLexer.h"
24#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Benjamin Kramerb3e8a6d2016-01-27 10:01:28 +000025#include "llvm/MC/MCParser/MCTargetAsmParser.h"
Simon Atanasyanbe186202016-02-11 06:45:54 +000026#include "llvm/MC/MCSectionELF.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000027#include "llvm/MC/MCStreamer.h"
28#include "llvm/MC/MCSubtargetInfo.h"
29#include "llvm/MC/MCSymbol.h"
Daniel Sandersb50ccf82014-04-01 10:35:28 +000030#include "llvm/Support/Debug.h"
Simon Atanasyanbe186202016-02-11 06:45:54 +000031#include "llvm/Support/ELF.h"
Matheus Almeidae0d75aa2013-12-13 11:11:02 +000032#include "llvm/Support/MathExtras.h"
Daniel Sandersef638fe2014-10-03 15:37:37 +000033#include "llvm/Support/SourceMgr.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000034#include "llvm/Support/TargetRegistry.h"
Benjamin Kramer799003b2015-03-23 19:32:43 +000035#include "llvm/Support/raw_ostream.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000036#include <memory>
Rafael Espindola870c4e92012-01-11 03:56:41 +000037
38using namespace llvm;
39
Chandler Carruthe96dd892014-04-21 22:55:11 +000040#define DEBUG_TYPE "mips-asm-parser"
41
Joey Gouly0e76fa72013-09-12 10:28:05 +000042namespace llvm {
43class MCInstrInfo;
44}
45
Rafael Espindola870c4e92012-01-11 03:56:41 +000046namespace {
Jack Carter0b744b32012-10-04 02:29:46 +000047class MipsAssemblerOptions {
48public:
Toma Tabacu465acfd2015-06-09 13:33:26 +000049 MipsAssemblerOptions(const FeatureBitset &Features_) :
Toma Tabacu9db22db2014-09-09 10:15:38 +000050 ATReg(1), Reorder(true), Macro(true), Features(Features_) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000051
Toma Tabacu9db22db2014-09-09 10:15:38 +000052 MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
Toma Tabacub19cf202015-04-27 13:12:59 +000053 ATReg = Opts->getATRegIndex();
Toma Tabacu9db22db2014-09-09 10:15:38 +000054 Reorder = Opts->isReorder();
55 Macro = Opts->isMacro();
56 Features = Opts->getFeatures();
57 }
58
Toma Tabacub19cf202015-04-27 13:12:59 +000059 unsigned getATRegIndex() const { return ATReg; }
60 bool setATRegIndex(unsigned Reg) {
Toma Tabacu92dbbf12015-03-26 13:08:55 +000061 if (Reg > 31)
62 return false;
63
64 ATReg = Reg;
65 return true;
66 }
Jack Carter0b744b32012-10-04 02:29:46 +000067
Toma Tabacu9db22db2014-09-09 10:15:38 +000068 bool isReorder() const { return Reorder; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000069 void setReorder() { Reorder = true; }
70 void setNoReorder() { Reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000071
Toma Tabacu9db22db2014-09-09 10:15:38 +000072 bool isMacro() const { return Macro; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000073 void setMacro() { Macro = true; }
74 void setNoMacro() { Macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000075
Toma Tabacu465acfd2015-06-09 13:33:26 +000076 const FeatureBitset &getFeatures() const { return Features; }
77 void setFeatures(const FeatureBitset &Features_) { Features = Features_; }
Toma Tabacu9db22db2014-09-09 10:15:38 +000078
Daniel Sandersf0df2212014-08-04 12:20:00 +000079 // Set of features that are either architecture features or referenced
80 // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6).
81 // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
82 // The reason we need this mask is explained in the selectArch function.
83 // FIXME: Ideally we would like TableGen to generate this information.
Michael Kupersteindb0712f2015-05-26 10:47:10 +000084 static const FeatureBitset AllArchRelatedMask;
Daniel Sandersf0df2212014-08-04 12:20:00 +000085
Jack Carter0b744b32012-10-04 02:29:46 +000086private:
Toma Tabacu3c24b042014-09-05 15:43:21 +000087 unsigned ATReg;
88 bool Reorder;
89 bool Macro;
Toma Tabacu465acfd2015-06-09 13:33:26 +000090 FeatureBitset Features;
Jack Carter0b744b32012-10-04 02:29:46 +000091};
92}
93
Michael Kupersteindb0712f2015-05-26 10:47:10 +000094const FeatureBitset MipsAssemblerOptions::AllArchRelatedMask = {
95 Mips::FeatureMips1, Mips::FeatureMips2, Mips::FeatureMips3,
96 Mips::FeatureMips3_32, Mips::FeatureMips3_32r2, Mips::FeatureMips4,
97 Mips::FeatureMips4_32, Mips::FeatureMips4_32r2, Mips::FeatureMips5,
98 Mips::FeatureMips5_32r2, Mips::FeatureMips32, Mips::FeatureMips32r2,
99 Mips::FeatureMips32r3, Mips::FeatureMips32r5, Mips::FeatureMips32r6,
100 Mips::FeatureMips64, Mips::FeatureMips64r2, Mips::FeatureMips64r3,
101 Mips::FeatureMips64r5, Mips::FeatureMips64r6, Mips::FeatureCnMips,
102 Mips::FeatureFP64Bit, Mips::FeatureGP64Bit, Mips::FeatureNaN2008
103};
104
Jack Carter0b744b32012-10-04 02:29:46 +0000105namespace {
Rafael Espindola870c4e92012-01-11 03:56:41 +0000106class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000107 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola961d4692014-11-11 05:18:41 +0000108 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000109 return static_cast<MipsTargetStreamer &>(TS);
110 }
111
Eric Christophera5762812015-01-26 17:33:46 +0000112 MipsABIInfo ABI;
Toma Tabacu9db22db2014-09-09 10:15:38 +0000113 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
Daniel Sandersd97a6342014-08-13 10:07:34 +0000114 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
115 // nullptr, which indicates that no function is currently
116 // selected. This usually happens after an '.end func'
117 // directive.
Toma Tabacud88d79c2015-06-23 14:39:42 +0000118 bool IsLittleEndian;
Daniel Sandersa6994442015-08-18 12:33:54 +0000119 bool IsPicEnabled;
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000120 bool IsCpRestoreSet;
121 int CpRestoreOffset;
Daniel Sandersf173dda2015-09-22 10:50:09 +0000122 unsigned CpSaveLocation;
123 /// If true, then CpSaveLocation is a register, otherwise it's an offset.
124 bool CpSaveLocationIsRegister;
Jack Carter0b744b32012-10-04 02:29:46 +0000125
Daniel Sandersef638fe2014-10-03 15:37:37 +0000126 // Print a warning along with its fix-it message at the given range.
127 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
128 SMRange Range, bool ShowColors = true);
129
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000130#define GET_ASSEMBLER_HEADER
131#include "MipsGenAsmMatcher.inc"
132
Matheus Almeida595fcab2014-06-11 15:05:56 +0000133 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
134
Chad Rosier49963552012-10-13 00:26:04 +0000135 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000136 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000137 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000138 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000139
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000140 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000141 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000142
Toma Tabacu13964452014-09-04 13:23:44 +0000143 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000144
Toma Tabacu13964452014-09-04 13:23:44 +0000145 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000146
David Blaikie960ea3f2014-06-08 16:18:35 +0000147 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
148 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000149
Craig Topper56c590a2014-04-29 07:58:02 +0000150 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000151
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000152 OperandMatchResultTy parseMemOperand(OperandVector &Operands);
153 OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000154 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000155 StringRef Identifier, SMLoc S);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000156 OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands,
157 SMLoc S);
158 OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
159 OperandMatchResultTy parseImm(OperandVector &Operands);
160 OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
161 OperandMatchResultTy parseInvNum(OperandVector &Operands);
162 OperandMatchResultTy parseLSAImm(OperandVector &Operands);
163 OperandMatchResultTy parseRegisterPair(OperandVector &Operands);
164 OperandMatchResultTy parseMovePRegPair(OperandVector &Operands);
165 OperandMatchResultTy parseRegisterList(OperandVector &Operands);
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000166
David Blaikie960ea3f2014-06-08 16:18:35 +0000167 bool searchSymbolAlias(OperandVector &Operands);
168
Toma Tabacu13964452014-09-04 13:23:44 +0000169 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000170
Daniel Sanders5bf6eab2015-10-26 23:50:00 +0000171 enum MacroExpanderResultTy {
172 MER_NotAMacro,
173 MER_Success,
174 MER_Fail,
175 };
Jack Carter30a59822012-10-04 04:03:53 +0000176
Matheus Almeida3813d572014-06-19 14:39:14 +0000177 // Expands assembly pseudo instructions.
Daniel Sanders5bf6eab2015-10-26 23:50:00 +0000178 MacroExpanderResultTy
179 tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
180 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000181
Toma Tabacu8f6603a2015-01-30 11:18:50 +0000182 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
183 SmallVectorImpl<MCInst> &Instructions);
184
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000185 bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000186 bool Is32BitImm, bool IsAddress, SMLoc IDLoc,
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000187 SmallVectorImpl<MCInst> &Instructions);
188
Toma Tabacuf712ede2015-06-17 14:31:51 +0000189 bool loadAndAddSymbolAddress(const MCExpr *SymExpr, unsigned DstReg,
190 unsigned SrcReg, bool Is32BitSym, SMLoc IDLoc,
191 SmallVectorImpl<MCInst> &Instructions);
Toma Tabacu674825c2015-06-16 12:16:24 +0000192
Toma Tabacu00e98672015-05-01 12:19:27 +0000193 bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000194 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000195
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000196 bool expandLoadAddress(unsigned DstReg, unsigned BaseReg,
197 const MCOperand &Offset, bool Is32BitAddress,
198 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000199
Jozef Kolek5cfebdd2015-01-21 12:39:30 +0000200 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
201 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000202
Jack Carter9e65aa32013-03-22 00:05:30 +0000203 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000204 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
205 bool isImmOpnd);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000206
207 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
208 SmallVectorImpl<MCInst> &Instructions);
209
Zoran Jovanoviccdb64562015-09-28 11:11:34 +0000210 bool expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
211 SmallVectorImpl<MCInst> &Instructions);
212
Toma Tabacue1e460d2015-06-11 10:36:10 +0000213 bool expandBranchImm(MCInst &Inst, SMLoc IDLoc,
214 SmallVectorImpl<MCInst> &Instructions);
215
Toma Tabacu1a108322015-06-17 13:20:24 +0000216 bool expandCondBranches(MCInst &Inst, SMLoc IDLoc,
217 SmallVectorImpl<MCInst> &Instructions);
218
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000219 bool expandDiv(MCInst &Inst, SMLoc IDLoc,
220 SmallVectorImpl<MCInst> &Instructions, const bool IsMips64,
221 const bool Signed);
222
Zoran Jovanovicd665a662016-02-22 16:00:23 +0000223 bool expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU, SMLoc IDLoc,
224 SmallVectorImpl<MCInst> &Instructions);
225
Daniel Sanders6394ee52015-10-15 14:52:58 +0000226 bool expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
227 SmallVectorImpl<MCInst> &Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000228
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +0000229 bool expandUlw(MCInst &Inst, SMLoc IDLoc,
230 SmallVectorImpl<MCInst> &Instructions);
231
Zoran Jovanovic00f998b2015-11-19 14:15:03 +0000232 bool expandRotation(MCInst &Inst, SMLoc IDLoc,
233 SmallVectorImpl<MCInst> &Instructions);
234 bool expandRotationImm(MCInst &Inst, SMLoc IDLoc,
235 SmallVectorImpl<MCInst> &Instructions);
236 bool expandDRotation(MCInst &Inst, SMLoc IDLoc,
237 SmallVectorImpl<MCInst> &Instructions);
238 bool expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
239 SmallVectorImpl<MCInst> &Instructions);
240
Zoran Jovanovicd474ef32016-01-29 16:18:34 +0000241 bool expandAbs(MCInst &Inst, SMLoc IDLoc,
242 SmallVectorImpl<MCInst> &Instructions);
243
Toma Tabacu234482a2015-03-16 12:03:39 +0000244 void createNop(bool hasShortDelaySlot, SMLoc IDLoc,
245 SmallVectorImpl<MCInst> &Instructions);
246
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000247 void createAddu(unsigned DstReg, unsigned SrcReg, unsigned TrgReg,
Toma Tabacu0b3e9782015-06-23 14:00:54 +0000248 bool Is64Bit, SmallVectorImpl<MCInst> &Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000249
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000250 void createCpRestoreMemOp(bool IsLoad, int StackOffset, SMLoc IDLoc,
251 SmallVectorImpl<MCInst> &Instructions);
252
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000253 bool reportParseError(Twine ErrorMsg);
254 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000255
Jack Carterb5cf5902013-04-17 00:18:04 +0000256 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000257 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000258
Vladimir Medic4c299852013-11-06 11:27:05 +0000259 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000260
261 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000262 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000263 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000264 bool parseSetFeature(uint64_t Feature);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000265 bool isPicAndNotNxxAbi(); // Used by .cpload, .cprestore, and .cpsetup.
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000266 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000267 bool parseDirectiveCpRestore(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000268 bool parseDirectiveCPSetup();
Daniel Sandersf173dda2015-09-22 10:50:09 +0000269 bool parseDirectiveCPReturn();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000270 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000271 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000272 bool parseDirectiveOption();
Toma Tabacu9ca50962015-04-16 09:53:47 +0000273 bool parseInsnDirective();
Simon Atanasyanbe186202016-02-11 06:45:54 +0000274 bool parseSSectionDirective(StringRef Section, unsigned Type);
Jack Carter0b744b32012-10-04 02:29:46 +0000275
276 bool parseSetAtDirective();
277 bool parseSetNoAtDirective();
278 bool parseSetMacroDirective();
279 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000280 bool parseSetMsaDirective();
281 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000282 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000283 bool parseSetReorderDirective();
284 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000285 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000286 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000287 bool parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +0000288 bool parseSetOddSPRegDirective();
289 bool parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000290 bool parseSetPopDirective();
291 bool parseSetPushDirective();
Toma Tabacu29696502015-06-02 09:48:04 +0000292 bool parseSetSoftFloatDirective();
293 bool parseSetHardFloatDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000294
Jack Carterd76b2372013-03-21 21:44:16 +0000295 bool parseSetAssignment();
296
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000297 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000298 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000299 bool parseDirectiveGpDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000300 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000301 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000302 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
303 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000304
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000305 bool parseInternalDirectiveReallowModule();
306
Jack Carterdc1e35d2012-09-06 20:00:02 +0000307 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000308
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000309 bool eatComma(StringRef ErrorStr);
310
Jack Carter1ac53222013-02-20 23:11:17 +0000311 int matchCPURegisterName(StringRef Symbol);
312
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000313 int matchHWRegsRegisterName(StringRef Symbol);
314
Jack Carter873c7242013-01-12 01:03:14 +0000315 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000316
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000317 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000318
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000319 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000320
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000321 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000322
Jack Carter5dc8ac92013-09-25 23:50:44 +0000323 int matchMSA128RegisterName(StringRef Name);
324
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000325 int matchMSA128CtrlRegisterName(StringRef Name);
326
Jack Carterd0bd6422013-04-18 00:41:53 +0000327 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000328
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000329 unsigned getGPR(int RegNo);
330
Toma Tabacu89a712b2015-04-15 10:48:56 +0000331 /// Returns the internal register number for the current AT. Also checks if
332 /// the current AT is unavailable (set to $0) and gives an error if it is.
333 /// This should be used in pseudo-instruction expansions which need AT.
334 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000335
336 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000337 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000338
339 // Helper function that checks if the value of a vector index is within the
340 // boundaries of accepted values for each RegisterKind
341 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
342 bool validateMSAIndex(int Val, int RegKind);
343
Daniel Sandersf0df2212014-08-04 12:20:00 +0000344 // Selects a new architecture by updating the FeatureBits with the necessary
345 // info including implied dependencies.
346 // Internally, it clears all the feature bits related to *any* architecture
347 // and selects the new one using the ToggleFeature functionality of the
348 // MCSubtargetInfo object that handles implied dependencies. The reason we
349 // clear all the arch related bits manually is because ToggleFeature only
350 // clears the features that imply the feature being cleared and not the
351 // features implied by the feature being cleared. This is easier to see
352 // with an example:
353 // --------------------------------------------------
354 // | Feature | Implies |
355 // | -------------------------------------------------|
356 // | FeatureMips1 | None |
357 // | FeatureMips2 | FeatureMips1 |
358 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
359 // | FeatureMips4 | FeatureMips3 |
360 // | ... | |
361 // --------------------------------------------------
362 //
363 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
364 // FeatureMipsGP64 | FeatureMips1)
365 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
366 void selectArch(StringRef ArchFeature) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000367 MCSubtargetInfo &STI = copySTI();
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000368 FeatureBitset FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000369 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
370 STI.setFeatureBits(FeatureBits);
371 setAvailableFeatures(
372 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000373 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000374 }
375
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000376 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000377 if (!(getSTI().getFeatureBits()[Feature])) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000378 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000379 setAvailableFeatures(
380 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000381 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000382 }
383 }
384
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000385 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000386 if (getSTI().getFeatureBits()[Feature]) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000387 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000388 setAvailableFeatures(
389 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000390 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000391 }
392 }
393
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000394 void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
395 setFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000396 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000397 }
398
399 void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
400 clearFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000401 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000402 }
403
Rafael Espindola870c4e92012-01-11 03:56:41 +0000404public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000405 enum MipsMatchResultTy {
Daniel Sanders52da7af2015-11-06 12:11:03 +0000406 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY,
Matheus Almeida595fcab2014-06-11 15:05:56 +0000407#define GET_OPERAND_DIAGNOSTIC_TYPES
408#include "MipsGenAsmMatcher.inc"
409#undef GET_OPERAND_DIAGNOSTIC_TYPES
Matheus Almeida595fcab2014-06-11 15:05:56 +0000410 };
411
Akira Hatanakab11ef082015-11-14 06:35:56 +0000412 MipsAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000413 const MCInstrInfo &MII, const MCTargetOptions &Options)
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000414 : MCTargetAsmParser(Options, sti),
Daniel Sanders50f17232015-09-15 16:17:27 +0000415 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
416 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000417 MCAsmParserExtension::Initialize(parser);
418
Toma Tabacu11e14a92015-04-21 11:50:52 +0000419 parser.addAliasForDirective(".asciiz", ".asciz");
420
Jack Carterb4dbc172012-09-05 23:34:03 +0000421 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000422 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000423
Toma Tabacu9db22db2014-09-09 10:15:38 +0000424 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000425 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000426 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000427
Toma Tabacu9db22db2014-09-09 10:15:38 +0000428 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000429 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000430 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000431
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000432 getTargetStreamer().updateABIInfo(*this);
433
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000434 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000435 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000436
437 CurrentFn = nullptr;
Toma Tabacud88d79c2015-06-23 14:39:42 +0000438
Daniel Sandersa6994442015-08-18 12:33:54 +0000439 IsPicEnabled =
440 (getContext().getObjectFileInfo()->getRelocM() == Reloc::PIC_);
441
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000442 IsCpRestoreSet = false;
443 CpRestoreOffset = -1;
444
Daniel Sanders50f17232015-09-15 16:17:27 +0000445 Triple TheTriple(sti.getTargetTriple());
446 if ((TheTriple.getArch() == Triple::mips) ||
447 (TheTriple.getArch() == Triple::mips64))
Toma Tabacud88d79c2015-06-23 14:39:42 +0000448 IsLittleEndian = false;
449 else
450 IsLittleEndian = true;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000451 }
452
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000453 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
454 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
455
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000456 bool isGP64bit() const {
457 return getSTI().getFeatureBits()[Mips::FeatureGP64Bit];
458 }
459 bool isFP64bit() const {
460 return getSTI().getFeatureBits()[Mips::FeatureFP64Bit];
461 }
Eric Christophera5762812015-01-26 17:33:46 +0000462 const MipsABIInfo &getABI() const { return ABI; }
463 bool isABI_N32() const { return ABI.IsN32(); }
464 bool isABI_N64() const { return ABI.IsN64(); }
465 bool isABI_O32() const { return ABI.IsO32(); }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000466 bool isABI_FPXX() const {
467 return getSTI().getFeatureBits()[Mips::FeatureFPXX];
468 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000469
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000470 bool useOddSPReg() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000471 return !(getSTI().getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000472 }
473
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000474 bool inMicroMipsMode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000475 return getSTI().getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000476 }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000477 bool hasMips1() const {
478 return getSTI().getFeatureBits()[Mips::FeatureMips1];
479 }
480 bool hasMips2() const {
481 return getSTI().getFeatureBits()[Mips::FeatureMips2];
482 }
483 bool hasMips3() const {
484 return getSTI().getFeatureBits()[Mips::FeatureMips3];
485 }
486 bool hasMips4() const {
487 return getSTI().getFeatureBits()[Mips::FeatureMips4];
488 }
489 bool hasMips5() const {
490 return getSTI().getFeatureBits()[Mips::FeatureMips5];
491 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000492 bool hasMips32() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000493 return getSTI().getFeatureBits()[Mips::FeatureMips32];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000494 }
495 bool hasMips64() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000496 return getSTI().getFeatureBits()[Mips::FeatureMips64];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000497 }
498 bool hasMips32r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000499 return getSTI().getFeatureBits()[Mips::FeatureMips32r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000500 }
501 bool hasMips64r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000502 return getSTI().getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000503 }
Daniel Sanders17793142015-02-18 16:24:50 +0000504 bool hasMips32r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000505 return (getSTI().getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000506 }
507 bool hasMips64r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000508 return (getSTI().getFeatureBits()[Mips::FeatureMips64r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000509 }
510 bool hasMips32r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000511 return (getSTI().getFeatureBits()[Mips::FeatureMips32r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000512 }
513 bool hasMips64r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000514 return (getSTI().getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000515 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000516 bool hasMips32r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000517 return getSTI().getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000518 }
519 bool hasMips64r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000520 return getSTI().getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000521 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000522
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000523 bool hasDSP() const {
524 return getSTI().getFeatureBits()[Mips::FeatureDSP];
525 }
526 bool hasDSPR2() const {
527 return getSTI().getFeatureBits()[Mips::FeatureDSPR2];
528 }
529 bool hasDSPR3() const {
530 return getSTI().getFeatureBits()[Mips::FeatureDSPR3];
531 }
532 bool hasMSA() const {
533 return getSTI().getFeatureBits()[Mips::FeatureMSA];
534 }
Kai Nackee0245392015-01-27 19:11:28 +0000535 bool hasCnMips() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000536 return (getSTI().getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000537 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000538
Daniel Sandersa6994442015-08-18 12:33:54 +0000539 bool inPicMode() {
540 return IsPicEnabled;
541 }
542
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000543 bool inMips16Mode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000544 return getSTI().getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000545 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000546
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000547 bool useTraps() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000548 return getSTI().getFeatureBits()[Mips::FeatureUseTCCInDIV];
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000549 }
550
Eric Christophere8ae3e32015-05-07 23:10:21 +0000551 bool useSoftFloat() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000552 return getSTI().getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000553 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000554
Toma Tabacud9d344b2015-04-27 14:05:04 +0000555 /// Warn if RegIndex is the same as the current AT.
556 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000557
558 void warnIfNoMacro(SMLoc Loc);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000559
560 bool isLittle() const { return IsLittleEndian; }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000561};
562}
563
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000564namespace {
565
566/// MipsOperand - Instances of this class represent a parsed Mips machine
567/// instruction.
568class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000569public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000570 /// Broad categories of register classes
571 /// The exact class is finalized by the render method.
572 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000573 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000574 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000575 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000576 RegKind_FCC = 4, /// FCC
577 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
578 RegKind_MSACtrl = 16, /// MSA control registers
579 RegKind_COP2 = 32, /// COP2
580 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
581 /// context).
582 RegKind_CCR = 128, /// CCR
583 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000584 RegKind_COP3 = 512, /// COP3
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000585 RegKind_COP0 = 1024, /// COP0
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000586 /// Potentially any (e.g. $1)
587 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
588 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000589 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
Jack Carter873c7242013-01-12 01:03:14 +0000590 };
591
592private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000593 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000594 k_Immediate, /// An immediate (possibly involving symbol references)
595 k_Memory, /// Base + Offset Memory Address
596 k_PhysRegister, /// A physical register from the Mips namespace
597 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000598 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000599 k_RegList, /// A physical register list
600 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000601 } Kind;
602
David Blaikie960ea3f2014-06-08 16:18:35 +0000603public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000604 MipsOperand(KindTy K, MipsAsmParser &Parser)
605 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
606
David Blaikie960ea3f2014-06-08 16:18:35 +0000607private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000608 /// For diagnostics, and checking the assembler temporary
609 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000610
Eric Christopher8996c5d2013-03-15 00:42:55 +0000611 struct Token {
612 const char *Data;
613 unsigned Length;
614 };
615
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000616 struct PhysRegOp {
617 unsigned Num; /// Register Number
618 };
619
620 struct RegIdxOp {
621 unsigned Index; /// Index into the register class
622 RegKind Kind; /// Bitfield of the kinds it could possibly be
623 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000624 };
625
626 struct ImmOp {
627 const MCExpr *Val;
628 };
629
630 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000631 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000632 const MCExpr *Off;
633 };
634
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000635 struct RegListOp {
636 SmallVector<unsigned, 10> *List;
637 };
638
Jack Carterb4dbc172012-09-05 23:34:03 +0000639 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000640 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000641 struct PhysRegOp PhysReg;
642 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000643 struct ImmOp Imm;
644 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000645 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000646 };
647
648 SMLoc StartLoc, EndLoc;
649
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000650 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000651 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
652 const MCRegisterInfo *RegInfo,
653 SMLoc S, SMLoc E,
654 MipsAsmParser &Parser) {
655 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000656 Op->RegIdx.Index = Index;
657 Op->RegIdx.RegInfo = RegInfo;
658 Op->RegIdx.Kind = RegKind;
659 Op->StartLoc = S;
660 Op->EndLoc = E;
661 return Op;
662 }
663
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000664public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000665 /// Coerce the register to GPR32 and return the real register for the current
666 /// target.
667 unsigned getGPR32Reg() const {
668 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000669 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000670 unsigned ClassID = Mips::GPR32RegClassID;
671 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000672 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000673
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000674 /// Coerce the register to GPR32 and return the real register for the current
675 /// target.
676 unsigned getGPRMM16Reg() const {
677 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
678 unsigned ClassID = Mips::GPR32RegClassID;
679 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
680 }
681
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000682 /// Coerce the register to GPR64 and return the real register for the current
683 /// target.
684 unsigned getGPR64Reg() const {
685 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
686 unsigned ClassID = Mips::GPR64RegClassID;
687 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000688 }
689
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000690private:
691 /// Coerce the register to AFGR64 and return the real register for the current
692 /// target.
693 unsigned getAFGR64Reg() const {
694 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
695 if (RegIdx.Index % 2 != 0)
696 AsmParser.Warning(StartLoc, "Float register should be even.");
697 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
698 .getRegister(RegIdx.Index / 2);
699 }
700
701 /// Coerce the register to FGR64 and return the real register for the current
702 /// target.
703 unsigned getFGR64Reg() const {
704 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
705 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
706 .getRegister(RegIdx.Index);
707 }
708
709 /// Coerce the register to FGR32 and return the real register for the current
710 /// target.
711 unsigned getFGR32Reg() const {
712 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
713 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
714 .getRegister(RegIdx.Index);
715 }
716
717 /// Coerce the register to FGRH32 and return the real register for the current
718 /// target.
719 unsigned getFGRH32Reg() const {
720 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
721 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
722 .getRegister(RegIdx.Index);
723 }
724
725 /// Coerce the register to FCC and return the real register for the current
726 /// target.
727 unsigned getFCCReg() const {
728 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
729 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
730 .getRegister(RegIdx.Index);
731 }
732
733 /// Coerce the register to MSA128 and return the real register for the current
734 /// target.
735 unsigned getMSA128Reg() const {
736 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
737 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
738 // identical
739 unsigned ClassID = Mips::MSA128BRegClassID;
740 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
741 }
742
743 /// Coerce the register to MSACtrl and return the real register for the
744 /// current target.
745 unsigned getMSACtrlReg() const {
746 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
747 unsigned ClassID = Mips::MSACtrlRegClassID;
748 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
749 }
750
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000751 /// Coerce the register to COP0 and return the real register for the
752 /// current target.
753 unsigned getCOP0Reg() const {
754 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");
755 unsigned ClassID = Mips::COP0RegClassID;
756 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
757 }
758
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000759 /// Coerce the register to COP2 and return the real register for the
760 /// current target.
761 unsigned getCOP2Reg() const {
762 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
763 unsigned ClassID = Mips::COP2RegClassID;
764 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
765 }
766
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000767 /// Coerce the register to COP3 and return the real register for the
768 /// current target.
769 unsigned getCOP3Reg() const {
770 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
771 unsigned ClassID = Mips::COP3RegClassID;
772 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
773 }
774
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000775 /// Coerce the register to ACC64DSP and return the real register for the
776 /// current target.
777 unsigned getACC64DSPReg() const {
778 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
779 unsigned ClassID = Mips::ACC64DSPRegClassID;
780 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
781 }
782
783 /// Coerce the register to HI32DSP and return the real register for the
784 /// current target.
785 unsigned getHI32DSPReg() const {
786 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
787 unsigned ClassID = Mips::HI32DSPRegClassID;
788 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
789 }
790
791 /// Coerce the register to LO32DSP and return the real register for the
792 /// current target.
793 unsigned getLO32DSPReg() const {
794 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
795 unsigned ClassID = Mips::LO32DSPRegClassID;
796 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
797 }
798
799 /// Coerce the register to CCR and return the real register for the
800 /// current target.
801 unsigned getCCRReg() const {
802 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
803 unsigned ClassID = Mips::CCRRegClassID;
804 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
805 }
806
807 /// Coerce the register to HWRegs and return the real register for the
808 /// current target.
809 unsigned getHWRegsReg() const {
810 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
811 unsigned ClassID = Mips::HWRegsRegClassID;
812 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
813 }
814
815public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000816 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000817 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000818 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000819 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000820 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000821 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000822 else
Jim Grosbache9119e42015-05-13 18:37:00 +0000823 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000824 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000825
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000826 void addRegOperands(MCInst &Inst, unsigned N) const {
827 llvm_unreachable("Use a custom parser instead");
828 }
829
Daniel Sanders21bce302014-04-01 12:35:23 +0000830 /// Render the operand to an MCInst as a GPR32
831 /// Asserts if the wrong number of operands are requested, or the operand
832 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000833 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
834 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000835 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000836 }
837
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000838 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
839 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000840 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000841 }
842
Jozef Kolek1904fa22014-11-24 14:25:53 +0000843 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
844 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000845 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +0000846 }
847
Zoran Jovanovic41688672015-02-10 16:36:20 +0000848 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
849 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000850 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000851 }
852
Daniel Sanders21bce302014-04-01 12:35:23 +0000853 /// Render the operand to an MCInst as a GPR64
854 /// Asserts if the wrong number of operands are requested, or the operand
855 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000856 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
857 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000858 Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000859 }
860
861 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
862 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000863 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000864 }
865
866 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
867 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000868 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000869 }
870
871 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
872 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000873 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000874 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000875 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000876 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
877 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000878 }
879
880 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
881 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000882 Inst.addOperand(MCOperand::createReg(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000883 }
884
885 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
886 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000887 Inst.addOperand(MCOperand::createReg(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000888 }
889
890 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
891 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000892 Inst.addOperand(MCOperand::createReg(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000893 }
894
895 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
896 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000897 Inst.addOperand(MCOperand::createReg(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000898 }
899
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000900 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
901 assert(N == 1 && "Invalid number of operands!");
902 Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
903 }
904
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000905 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
906 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000907 Inst.addOperand(MCOperand::createReg(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000908 }
909
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000910 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
911 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000912 Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000913 }
914
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000915 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
916 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000917 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000918 }
919
920 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
921 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000922 Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000923 }
924
925 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
926 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000927 Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000928 }
929
930 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
931 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000932 Inst.addOperand(MCOperand::createReg(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000933 }
934
935 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
936 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000937 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000938 }
939
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +0000940 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
Daniel Sanders52da7af2015-11-06 12:11:03 +0000941 void addConstantUImmOperands(MCInst &Inst, unsigned N) const {
942 assert(N == 1 && "Invalid number of operands!");
Daniel Sandersea4f6532015-11-06 12:22:31 +0000943 uint64_t Imm = getConstantImm() - Offset;
944 Imm &= (1 << Bits) - 1;
945 Imm += Offset;
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +0000946 Imm += AdjustOffset;
Daniel Sanders52da7af2015-11-06 12:11:03 +0000947 Inst.addOperand(MCOperand::createImm(Imm));
948 }
949
Daniel Sandersf8bb23e2016-02-01 15:13:31 +0000950 template <unsigned Bits>
951 void addUImmOperands(MCInst &Inst, unsigned N) const {
952 if (isImm() && !isConstantImm()) {
953 addExpr(Inst, getImm());
954 return;
955 }
956 addConstantUImmOperands<Bits, 0, 0>(Inst, N);
957 }
958
Daniel Sanders78e89022016-03-11 11:37:50 +0000959 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
960 void addConstantSImmOperands(MCInst &Inst, unsigned N) const {
961 assert(N == 1 && "Invalid number of operands!");
962 int64_t Imm = getConstantImm() - Offset;
963 Imm = SignExtend64<Bits>(Imm);
964 Imm += Offset;
965 Imm += AdjustOffset;
966 Inst.addOperand(MCOperand::createImm(Imm));
967 }
968
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000969 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000970 assert(N == 1 && "Invalid number of operands!");
971 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000972 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000973 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000974
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000975 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000976 assert(N == 2 && "Invalid number of operands!");
977
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000978 Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
979 ? getMemBase()->getGPR64Reg()
980 : getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000981
982 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000983 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000984 }
985
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000986 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
987 assert(N == 2 && "Invalid number of operands!");
988
Jim Grosbache9119e42015-05-13 18:37:00 +0000989 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000990
991 const MCExpr *Expr = getMemOff();
992 addExpr(Inst, Expr);
993 }
994
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000995 void addRegListOperands(MCInst &Inst, unsigned N) const {
996 assert(N == 1 && "Invalid number of operands!");
997
998 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000999 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001000 }
1001
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001002 void addRegPairOperands(MCInst &Inst, unsigned N) const {
1003 assert(N == 2 && "Invalid number of operands!");
1004 unsigned RegNo = getRegPair();
Jim Grosbache9119e42015-05-13 18:37:00 +00001005 Inst.addOperand(MCOperand::createReg(RegNo++));
1006 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001007 }
1008
Zoran Jovanovic41688672015-02-10 16:36:20 +00001009 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
1010 assert(N == 2 && "Invalid number of operands!");
1011 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001012 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +00001013 }
1014
Craig Topper56c590a2014-04-29 07:58:02 +00001015 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001016 // As a special case until we sort out the definition of div/divu, pretend
1017 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
1018 if (isGPRAsmReg() && RegIdx.Index == 0)
1019 return true;
1020
1021 return Kind == k_PhysRegister;
1022 }
1023 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +00001024 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001025 bool isConstantImm() const {
Craig Topper66059c92015-11-18 07:07:59 +00001026 return isImm() && isa<MCConstantExpr>(getImm());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001027 }
Daniel Sanders52da7af2015-11-06 12:11:03 +00001028 bool isConstantImmz() const {
1029 return isConstantImm() && getConstantImm() == 0;
1030 }
Daniel Sandersea4f6532015-11-06 12:22:31 +00001031 template <unsigned Bits, int Offset = 0> bool isConstantUImm() const {
1032 return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset);
1033 }
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001034 template <unsigned Bits> bool isUImm() const {
1035 return isConstantImm() ? isUInt<Bits>(getConstantImm()) : isImm();
1036 }
1037 template <unsigned Bits> bool isAnyImm() const {
1038 return isConstantImm() ? (isInt<Bits>(getConstantImm()) ||
1039 isUInt<Bits>(getConstantImm()))
1040 : isImm();
1041 }
Daniel Sanders78e89022016-03-11 11:37:50 +00001042 template <unsigned Bits, int Offset = 0> bool isConstantSImm() const {
1043 return isConstantImm() && isInt<Bits>(getConstantImm() - Offset);
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +00001044 }
Hrvoje Varga46458d02016-02-25 12:53:29 +00001045 template <unsigned Bottom, unsigned Top> bool isConstantUImmRange() const {
1046 return isConstantImm() && getConstantImm() >= Bottom &&
1047 getConstantImm() <= Top;
1048 }
Craig Topper56c590a2014-04-29 07:58:02 +00001049 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001050 // Note: It's not possible to pretend that other operand kinds are tokens.
1051 // The matcher emitter checks tokens first.
1052 return Kind == k_Token;
1053 }
Craig Topper56c590a2014-04-29 07:58:02 +00001054 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001055 bool isConstantMemOff() const {
Craig Topper66059c92015-11-18 07:07:59 +00001056 return isMem() && isa<MCConstantExpr>(getMemOff());
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001057 }
1058 template <unsigned Bits> bool isMemWithSimmOffset() const {
Zoran Jovanovica6593ff2015-08-18 12:53:08 +00001059 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
1060 && getMemBase()->isGPRAsmReg();
1061 }
Zoran Jovanovic6e6a2c92015-09-16 09:14:35 +00001062 template <unsigned Bits> bool isMemWithSimmOffsetGPR() const {
1063 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff()) &&
1064 getMemBase()->isGPRAsmReg();
1065 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001066 bool isMemWithGRPMM16Base() const {
1067 return isMem() && getMemBase()->isMM16AsmReg();
1068 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001069 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
1070 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1071 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
1072 }
Jozef Kolek12c69822014-12-23 16:16:33 +00001073 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
1074 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1075 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1076 && (getMemBase()->getGPR32Reg() == Mips::SP);
1077 }
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001078 template <unsigned Bits, unsigned ShiftLeftAmount>
1079 bool isScaledUImm() const {
1080 return isConstantImm() &&
1081 isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm());
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00001082 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001083 bool isRegList16() const {
1084 if (!isRegList())
1085 return false;
1086
1087 int Size = RegList.List->size();
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001088 if (Size < 2 || Size > 5)
1089 return false;
1090
1091 unsigned R0 = RegList.List->front();
1092 unsigned R1 = RegList.List->back();
1093 if (!((R0 == Mips::S0 && R1 == Mips::RA) ||
1094 (R0 == Mips::S0_64 && R1 == Mips::RA_64)))
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001095 return false;
1096
1097 int PrevReg = *RegList.List->begin();
1098 for (int i = 1; i < Size - 1; i++) {
1099 int Reg = (*(RegList.List))[i];
1100 if ( Reg != PrevReg + 1)
1101 return false;
1102 PrevReg = Reg;
1103 }
1104
1105 return true;
1106 }
Vladimir Medic2b953d02013-10-01 09:48:56 +00001107 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001108 bool isLSAImm() const {
1109 if (!isConstantImm())
1110 return false;
1111 int64_t Val = getConstantImm();
1112 return 1 <= Val && Val <= 4;
1113 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001114 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001115 bool isMovePRegPair() const {
1116 if (Kind != k_RegList || RegList.List->size() != 2)
1117 return false;
1118
1119 unsigned R0 = RegList.List->front();
1120 unsigned R1 = RegList.List->back();
1121
1122 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
1123 (R0 == Mips::A1 && R1 == Mips::A3) ||
1124 (R0 == Mips::A2 && R1 == Mips::A3) ||
1125 (R0 == Mips::A0 && R1 == Mips::S5) ||
1126 (R0 == Mips::A0 && R1 == Mips::S6) ||
1127 (R0 == Mips::A0 && R1 == Mips::A1) ||
1128 (R0 == Mips::A0 && R1 == Mips::A2) ||
1129 (R0 == Mips::A0 && R1 == Mips::A3))
1130 return true;
1131
1132 return false;
1133 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001134
1135 StringRef getToken() const {
1136 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001137 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001138 }
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001139 bool isRegPair() const { return Kind == k_RegPair; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001140
Craig Topper56c590a2014-04-29 07:58:02 +00001141 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001142 // As a special case until we sort out the definition of div/divu, pretend
1143 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
1144 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1145 RegIdx.Kind & RegKind_GPR)
1146 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001147
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001148 assert(Kind == k_PhysRegister && "Invalid access!");
1149 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +00001150 }
1151
Jack Carterb4dbc172012-09-05 23:34:03 +00001152 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001153 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001154 return Imm.Val;
1155 }
1156
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001157 int64_t getConstantImm() const {
1158 const MCExpr *Val = getImm();
1159 return static_cast<const MCConstantExpr *>(Val)->getValue();
1160 }
1161
1162 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001163 assert((Kind == k_Memory) && "Invalid access!");
1164 return Mem.Base;
1165 }
1166
1167 const MCExpr *getMemOff() const {
1168 assert((Kind == k_Memory) && "Invalid access!");
1169 return Mem.Off;
1170 }
1171
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001172 int64_t getConstantMemOff() const {
1173 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1174 }
1175
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001176 const SmallVectorImpl<unsigned> &getRegList() const {
1177 assert((Kind == k_RegList) && "Invalid access!");
1178 return *(RegList.List);
1179 }
1180
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001181 unsigned getRegPair() const {
1182 assert((Kind == k_RegPair) && "Invalid access!");
1183 return RegIdx.Index;
1184 }
1185
David Blaikie960ea3f2014-06-08 16:18:35 +00001186 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1187 MipsAsmParser &Parser) {
1188 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001189 Op->Tok.Data = Str.data();
1190 Op->Tok.Length = Str.size();
1191 Op->StartLoc = S;
1192 Op->EndLoc = S;
1193 return Op;
1194 }
1195
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001196 /// Create a numeric register (e.g. $1). The exact register remains
1197 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001198 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001199 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001200 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001201 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001202 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001203 }
1204
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001205 /// Create a register that is definitely a GPR.
1206 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001207 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001208 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001209 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001210 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001211 }
1212
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001213 /// Create a register that is definitely a FGR.
1214 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001215 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001216 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001217 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001218 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
1219 }
1220
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001221 /// Create a register that is definitely a HWReg.
1222 /// This is typically only used for named registers such as $hwr_cpunum.
1223 static std::unique_ptr<MipsOperand>
1224 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
1225 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1226 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
1227 }
1228
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001229 /// Create a register that is definitely an FCC.
1230 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001231 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001232 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001233 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001234 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
1235 }
1236
1237 /// Create a register that is definitely an ACC.
1238 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001239 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001240 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001241 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001242 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
1243 }
1244
1245 /// Create a register that is definitely an MSA128.
1246 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001247 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001248 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001249 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001250 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
1251 }
1252
1253 /// Create a register that is definitely an MSACtrl.
1254 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001255 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001256 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001257 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001258 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
1259 }
1260
David Blaikie960ea3f2014-06-08 16:18:35 +00001261 static std::unique_ptr<MipsOperand>
1262 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1263 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001264 Op->Imm.Val = Val;
1265 Op->StartLoc = S;
1266 Op->EndLoc = E;
1267 return Op;
1268 }
1269
David Blaikie960ea3f2014-06-08 16:18:35 +00001270 static std::unique_ptr<MipsOperand>
1271 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1272 SMLoc E, MipsAsmParser &Parser) {
1273 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1274 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001275 Op->Mem.Off = Off;
1276 Op->StartLoc = S;
1277 Op->EndLoc = E;
1278 return Op;
1279 }
1280
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001281 static std::unique_ptr<MipsOperand>
1282 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1283 MipsAsmParser &Parser) {
1284 assert (Regs.size() > 0 && "Empty list not allowed");
1285
1286 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001287 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001288 Op->StartLoc = StartLoc;
1289 Op->EndLoc = EndLoc;
1290 return Op;
1291 }
1292
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001293 static std::unique_ptr<MipsOperand>
1294 CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1295 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
1296 Op->RegIdx.Index = RegNo;
1297 Op->StartLoc = S;
1298 Op->EndLoc = E;
1299 return Op;
1300 }
1301
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001302 bool isGPRAsmReg() const {
1303 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001304 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001305 bool isMM16AsmReg() const {
1306 if (!(isRegIdx() && RegIdx.Kind))
1307 return false;
1308 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1309 || RegIdx.Index == 16 || RegIdx.Index == 17);
1310 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001311 bool isMM16AsmRegZero() const {
1312 if (!(isRegIdx() && RegIdx.Kind))
1313 return false;
1314 return (RegIdx.Index == 0 ||
1315 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1316 RegIdx.Index == 17);
1317 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001318 bool isMM16AsmRegMoveP() const {
1319 if (!(isRegIdx() && RegIdx.Kind))
1320 return false;
1321 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1322 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1323 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001324 bool isFGRAsmReg() const {
1325 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1326 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001327 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001328 bool isHWRegsAsmReg() const {
1329 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001330 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001331 bool isCCRAsmReg() const {
1332 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001333 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001334 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001335 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1336 return false;
1337 if (!AsmParser.hasEightFccRegisters())
1338 return RegIdx.Index == 0;
1339 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001340 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001341 bool isACCAsmReg() const {
1342 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001343 }
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001344 bool isCOP0AsmReg() const {
1345 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1346 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001347 bool isCOP2AsmReg() const {
1348 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001349 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001350 bool isCOP3AsmReg() const {
1351 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1352 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001353 bool isMSA128AsmReg() const {
1354 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001355 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001356 bool isMSACtrlAsmReg() const {
1357 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001358 }
1359
Jack Carterb4dbc172012-09-05 23:34:03 +00001360 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001361 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001362 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001363 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001364
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001365 virtual ~MipsOperand() {
1366 switch (Kind) {
1367 case k_Immediate:
1368 break;
1369 case k_Memory:
1370 delete Mem.Base;
1371 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001372 case k_RegList:
1373 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001374 case k_PhysRegister:
1375 case k_RegisterIndex:
1376 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001377 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001378 break;
1379 }
1380 }
1381
Craig Topper56c590a2014-04-29 07:58:02 +00001382 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001383 switch (Kind) {
1384 case k_Immediate:
1385 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001386 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001387 OS << ">";
1388 break;
1389 case k_Memory:
1390 OS << "Mem<";
1391 Mem.Base->print(OS);
1392 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001393 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001394 OS << ">";
1395 break;
1396 case k_PhysRegister:
1397 OS << "PhysReg<" << PhysReg.Num << ">";
1398 break;
1399 case k_RegisterIndex:
1400 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1401 break;
1402 case k_Token:
1403 OS << Tok.Data;
1404 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001405 case k_RegList:
1406 OS << "RegList< ";
1407 for (auto Reg : (*RegList.List))
1408 OS << Reg << " ";
1409 OS << ">";
1410 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001411 case k_RegPair:
1412 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1413 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001414 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001415 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001416}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001417} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001418
Jack Carter9e65aa32013-03-22 00:05:30 +00001419namespace llvm {
1420extern const MCInstrDesc MipsInsts[];
1421}
1422static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1423 return MipsInsts[Opcode];
1424}
1425
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001426static bool hasShortDelaySlot(unsigned Opcode) {
1427 switch (Opcode) {
1428 case Mips::JALS_MM:
1429 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001430 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001431 case Mips::BGEZALS_MM:
1432 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001433 return true;
1434 default:
1435 return false;
1436 }
1437}
1438
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001439static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1440 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1441 return &SRExpr->getSymbol();
1442 }
1443
1444 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1445 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1446 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1447
1448 if (LHSSym)
1449 return LHSSym;
1450
1451 if (RHSSym)
1452 return RHSSym;
1453
1454 return nullptr;
1455 }
1456
1457 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1458 return getSingleMCSymbol(UExpr->getSubExpr());
1459
1460 return nullptr;
1461}
1462
1463static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1464 if (isa<MCSymbolRefExpr>(Expr))
1465 return 1;
1466
1467 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1468 return countMCSymbolRefExpr(BExpr->getLHS()) +
1469 countMCSymbolRefExpr(BExpr->getRHS());
1470
1471 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1472 return countMCSymbolRefExpr(UExpr->getSubExpr());
1473
1474 return 0;
1475}
1476
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001477namespace {
1478void emitRX(unsigned Opcode, unsigned Reg0, MCOperand Op1, SMLoc IDLoc,
1479 SmallVectorImpl<MCInst> &Instructions) {
1480 MCInst tmpInst;
1481 tmpInst.setOpcode(Opcode);
1482 tmpInst.addOperand(MCOperand::createReg(Reg0));
1483 tmpInst.addOperand(Op1);
1484 tmpInst.setLoc(IDLoc);
1485 Instructions.push_back(tmpInst);
1486}
1487
1488void emitRI(unsigned Opcode, unsigned Reg0, int32_t Imm, SMLoc IDLoc,
1489 SmallVectorImpl<MCInst> &Instructions) {
1490 emitRX(Opcode, Reg0, MCOperand::createImm(Imm), IDLoc, Instructions);
1491}
1492
1493void emitRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, SMLoc IDLoc,
1494 SmallVectorImpl<MCInst> &Instructions) {
1495 emitRX(Opcode, Reg0, MCOperand::createReg(Reg1), IDLoc, Instructions);
1496}
1497
1498void emitII(unsigned Opcode, int16_t Imm1, int16_t Imm2, SMLoc IDLoc,
1499 SmallVectorImpl<MCInst> &Instructions) {
1500 MCInst tmpInst;
1501 tmpInst.setOpcode(Opcode);
1502 tmpInst.addOperand(MCOperand::createImm(Imm1));
1503 tmpInst.addOperand(MCOperand::createImm(Imm2));
1504 tmpInst.setLoc(IDLoc);
1505 Instructions.push_back(tmpInst);
1506}
1507
1508void emitR(unsigned Opcode, unsigned Reg0, SMLoc IDLoc,
1509 SmallVectorImpl<MCInst> &Instructions) {
1510 MCInst tmpInst;
1511 tmpInst.setOpcode(Opcode);
1512 tmpInst.addOperand(MCOperand::createReg(Reg0));
1513 tmpInst.setLoc(IDLoc);
1514 Instructions.push_back(tmpInst);
1515}
1516
1517void emitRRX(unsigned Opcode, unsigned Reg0, unsigned Reg1, MCOperand Op2,
1518 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1519 MCInst tmpInst;
1520 tmpInst.setOpcode(Opcode);
1521 tmpInst.addOperand(MCOperand::createReg(Reg0));
1522 tmpInst.addOperand(MCOperand::createReg(Reg1));
1523 tmpInst.addOperand(Op2);
1524 tmpInst.setLoc(IDLoc);
1525 Instructions.push_back(tmpInst);
1526}
1527
1528void emitRRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, unsigned Reg2,
1529 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1530 emitRRX(Opcode, Reg0, Reg1, MCOperand::createReg(Reg2), IDLoc,
1531 Instructions);
1532}
1533
1534void emitRRI(unsigned Opcode, unsigned Reg0, unsigned Reg1, int16_t Imm,
1535 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1536 emitRRX(Opcode, Reg0, Reg1, MCOperand::createImm(Imm), IDLoc,
1537 Instructions);
1538}
1539
1540void emitAppropriateDSLL(unsigned DstReg, unsigned SrcReg, int16_t ShiftAmount,
1541 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1542 if (ShiftAmount >= 32) {
1543 emitRRI(Mips::DSLL32, DstReg, SrcReg, ShiftAmount - 32, IDLoc,
1544 Instructions);
1545 return;
1546 }
1547
1548 emitRRI(Mips::DSLL, DstReg, SrcReg, ShiftAmount, IDLoc, Instructions);
1549}
1550} // end anonymous namespace.
1551
Jack Carter9e65aa32013-03-22 00:05:30 +00001552bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001553 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001554 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001555 bool ExpandedJalSym = false;
Daniel Sandersa771fef2014-03-24 14:05:39 +00001556
Jack Carter9e65aa32013-03-22 00:05:30 +00001557 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001558
1559 if (MCID.isBranch() || MCID.isCall()) {
1560 const unsigned Opcode = Inst.getOpcode();
1561 MCOperand Offset;
1562
1563 switch (Opcode) {
1564 default:
1565 break;
Kai Nackee0245392015-01-27 19:11:28 +00001566 case Mips::BBIT0:
1567 case Mips::BBIT032:
1568 case Mips::BBIT1:
1569 case Mips::BBIT132:
1570 assert(hasCnMips() && "instruction only valid for octeon cpus");
1571 // Fall through
1572
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001573 case Mips::BEQ:
1574 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001575 case Mips::BEQ_MM:
1576 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001577 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001578 Offset = Inst.getOperand(2);
1579 if (!Offset.isImm())
1580 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001581 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001582 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001583 if (OffsetToAlignment(Offset.getImm(),
1584 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001585 return Error(IDLoc, "branch to misaligned address");
1586 break;
1587 case Mips::BGEZ:
1588 case Mips::BGTZ:
1589 case Mips::BLEZ:
1590 case Mips::BLTZ:
1591 case Mips::BGEZAL:
1592 case Mips::BLTZAL:
1593 case Mips::BC1F:
1594 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001595 case Mips::BGEZ_MM:
1596 case Mips::BGTZ_MM:
1597 case Mips::BLEZ_MM:
1598 case Mips::BLTZ_MM:
1599 case Mips::BGEZAL_MM:
1600 case Mips::BLTZAL_MM:
1601 case Mips::BC1F_MM:
1602 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001603 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001604 Offset = Inst.getOperand(1);
1605 if (!Offset.isImm())
1606 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001607 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001608 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001609 if (OffsetToAlignment(Offset.getImm(),
1610 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001611 return Error(IDLoc, "branch to misaligned address");
1612 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001613 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001614 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001615 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001616 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001617 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1618 Offset = Inst.getOperand(1);
1619 if (!Offset.isImm())
1620 break; // We'll deal with this situation later on when applying fixups.
Craig Topper55b1f292015-10-10 20:17:07 +00001621 if (!isInt<8>(Offset.getImm()))
Jozef Kolek9761e962015-01-12 12:03:34 +00001622 return Error(IDLoc, "branch target out of range");
1623 if (OffsetToAlignment(Offset.getImm(), 2LL))
1624 return Error(IDLoc, "branch to misaligned address");
1625 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001626 }
1627 }
1628
Daniel Sandersa84989a2014-06-16 13:25:35 +00001629 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1630 // We still accept it but it is a normal nop.
1631 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1632 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1633 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1634 "nop instruction");
1635 }
1636
Kai Nackee0245392015-01-27 19:11:28 +00001637 if (hasCnMips()) {
1638 const unsigned Opcode = Inst.getOpcode();
1639 MCOperand Opnd;
1640 int Imm;
1641
1642 switch (Opcode) {
1643 default:
1644 break;
1645
1646 case Mips::BBIT0:
1647 case Mips::BBIT032:
1648 case Mips::BBIT1:
1649 case Mips::BBIT132:
1650 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1651 // The offset is handled above
1652 Opnd = Inst.getOperand(1);
1653 if (!Opnd.isImm())
1654 return Error(IDLoc, "expected immediate operand kind");
1655 Imm = Opnd.getImm();
1656 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1657 Opcode == Mips::BBIT1 ? 63 : 31))
1658 return Error(IDLoc, "immediate operand value out of range");
1659 if (Imm > 31) {
1660 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1661 : Mips::BBIT132);
1662 Inst.getOperand(1).setImm(Imm - 32);
1663 }
1664 break;
1665
Kai Nackee0245392015-01-27 19:11:28 +00001666 case Mips::SEQi:
1667 case Mips::SNEi:
1668 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1669 Opnd = Inst.getOperand(2);
1670 if (!Opnd.isImm())
1671 return Error(IDLoc, "expected immediate operand kind");
1672 Imm = Opnd.getImm();
1673 if (!isInt<10>(Imm))
1674 return Error(IDLoc, "immediate operand value out of range");
1675 break;
1676 }
1677 }
1678
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001679 // This expansion is not in a function called by tryExpandInstruction()
1680 // because the pseudo-instruction doesn't have a distinct opcode.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001681 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
1682 inPicMode()) {
1683 warnIfNoMacro(IDLoc);
1684
1685 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
1686
1687 // We can do this expansion if there's only 1 symbol in the argument
1688 // expression.
1689 if (countMCSymbolRefExpr(JalExpr) > 1)
1690 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
1691
1692 // FIXME: This is checking the expression can be handled by the later stages
1693 // of the assembler. We ought to leave it to those later stages but
1694 // we can't do that until we stop evaluateRelocExpr() rewriting the
1695 // expressions into non-equivalent forms.
1696 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
1697
1698 // FIXME: Add support for label+offset operands (currently causes an error).
1699 // FIXME: Add support for forward-declared local symbols.
1700 // FIXME: Add expansion for when the LargeGOT option is enabled.
1701 if (JalSym->isInSection() || JalSym->isTemporary()) {
1702 if (isABI_O32()) {
1703 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001704 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001705 // R_(MICRO)MIPS_GOT16 label
1706 // addiu $25, $25, 0
1707 // R_(MICRO)MIPS_LO16 label
1708 // jalr $25
1709 const MCExpr *Got16RelocExpr = evaluateRelocExpr(JalExpr, "got");
1710 const MCExpr *Lo16RelocExpr = evaluateRelocExpr(JalExpr, "lo");
1711
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001712 emitRRX(Mips::LW, Mips::T9, Mips::GP,
1713 MCOperand::createExpr(Got16RelocExpr), IDLoc, Instructions);
1714 emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
1715 MCOperand::createExpr(Lo16RelocExpr), IDLoc, Instructions);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001716 } else if (isABI_N32() || isABI_N64()) {
1717 // If it's a local symbol and the N32/N64 ABIs are being used,
1718 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001719 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001720 // R_(MICRO)MIPS_GOT_DISP label
1721 // jalr $25
1722 const MCExpr *GotDispRelocExpr = evaluateRelocExpr(JalExpr, "got_disp");
1723
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001724 emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
1725 MCOperand::createExpr(GotDispRelocExpr), IDLoc, Instructions);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001726 }
1727 } else {
Daniel Sandersb7002032015-11-20 13:16:35 +00001728 // If it's an external/weak symbol, we expand to:
1729 // lw/ld $25, 0($gp)
1730 // R_(MICRO)MIPS_CALL16 label
1731 // jalr $25
1732 const MCExpr *Call16RelocExpr = evaluateRelocExpr(JalExpr, "call16");
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001733
Daniel Sandersb7002032015-11-20 13:16:35 +00001734 emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
1735 MCOperand::createExpr(Call16RelocExpr), IDLoc, Instructions);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001736 }
1737
1738 MCInst JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001739 if (IsCpRestoreSet && inMicroMipsMode())
1740 JalrInst.setOpcode(Mips::JALRS_MM);
1741 else
1742 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001743 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
1744 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
1745
1746 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
1747 // This relocation is supposed to be an optimization hint for the linker
1748 // and is not necessary for correctness.
1749
1750 Inst = JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001751 ExpandedJalSym = true;
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001752 }
1753
Jack Carter9e65aa32013-03-22 00:05:30 +00001754 if (MCID.mayLoad() || MCID.mayStore()) {
1755 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001756 // reference or immediate we may have to expand instructions.
1757 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001758 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001759 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1760 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001761 MCOperand &Op = Inst.getOperand(i);
1762 if (Op.isImm()) {
1763 int MemOffset = Op.getImm();
1764 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001765 // Offset can't exceed 16bit value.
1766 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001767 return false;
1768 }
1769 } else if (Op.isExpr()) {
1770 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001771 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001772 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001773 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001774 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001775 // Expand symbol.
1776 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001777 return false;
1778 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001779 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001780 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001781 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001782 }
1783 }
1784 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001785 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001786 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001787
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001788 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001789 if (MCID.mayLoad()) {
1790 // Try to create 16-bit GP relative load instruction.
1791 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1792 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1793 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1794 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1795 MCOperand &Op = Inst.getOperand(i);
1796 if (Op.isImm()) {
1797 int MemOffset = Op.getImm();
1798 MCOperand &DstReg = Inst.getOperand(0);
1799 MCOperand &BaseReg = Inst.getOperand(1);
Craig Topper55b1f292015-10-10 20:17:07 +00001800 if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&
Jozef Koleke10a02e2015-01-28 17:27:26 +00001801 getContext().getRegisterInfo()->getRegClass(
1802 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00001803 (BaseReg.getReg() == Mips::GP ||
1804 BaseReg.getReg() == Mips::GP_64)) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001805
1806 emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
1807 IDLoc, Instructions);
Jozef Koleke10a02e2015-01-28 17:27:26 +00001808 return false;
1809 }
1810 }
1811 }
1812 } // for
1813 } // if load
1814
1815 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1816
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001817 MCOperand Opnd;
1818 int Imm;
1819
1820 switch (Inst.getOpcode()) {
1821 default:
1822 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001823 case Mips::ADDIUSP_MM:
1824 Opnd = Inst.getOperand(0);
1825 if (!Opnd.isImm())
1826 return Error(IDLoc, "expected immediate operand kind");
1827 Imm = Opnd.getImm();
1828 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1829 Imm % 4 != 0)
1830 return Error(IDLoc, "immediate operand value out of range");
1831 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001832 case Mips::SLL16_MM:
1833 case Mips::SRL16_MM:
1834 Opnd = Inst.getOperand(2);
1835 if (!Opnd.isImm())
1836 return Error(IDLoc, "expected immediate operand kind");
1837 Imm = Opnd.getImm();
1838 if (Imm < 1 || Imm > 8)
1839 return Error(IDLoc, "immediate operand value out of range");
1840 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001841 case Mips::LI16_MM:
1842 Opnd = Inst.getOperand(1);
1843 if (!Opnd.isImm())
1844 return Error(IDLoc, "expected immediate operand kind");
1845 Imm = Opnd.getImm();
1846 if (Imm < -1 || Imm > 126)
1847 return Error(IDLoc, "immediate operand value out of range");
1848 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001849 case Mips::ADDIUR2_MM:
1850 Opnd = Inst.getOperand(2);
1851 if (!Opnd.isImm())
1852 return Error(IDLoc, "expected immediate operand kind");
1853 Imm = Opnd.getImm();
1854 if (!(Imm == 1 || Imm == -1 ||
1855 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1856 return Error(IDLoc, "immediate operand value out of range");
1857 break;
Zoran Jovanovic42b84442014-10-23 11:13:59 +00001858 case Mips::ADDIUR1SP_MM:
1859 Opnd = Inst.getOperand(1);
1860 if (!Opnd.isImm())
1861 return Error(IDLoc, "expected immediate operand kind");
1862 Imm = Opnd.getImm();
1863 if (OffsetToAlignment(Imm, 4LL))
1864 return Error(IDLoc, "misaligned immediate operand value");
1865 if (Imm < 0 || Imm > 255)
1866 return Error(IDLoc, "immediate operand value out of range");
1867 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001868 case Mips::ANDI16_MM:
1869 Opnd = Inst.getOperand(2);
1870 if (!Opnd.isImm())
1871 return Error(IDLoc, "expected immediate operand kind");
1872 Imm = Opnd.getImm();
1873 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1874 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1875 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1876 return Error(IDLoc, "immediate operand value out of range");
1877 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001878 case Mips::LBU16_MM:
1879 Opnd = Inst.getOperand(2);
1880 if (!Opnd.isImm())
1881 return Error(IDLoc, "expected immediate operand kind");
1882 Imm = Opnd.getImm();
1883 if (Imm < -1 || Imm > 14)
1884 return Error(IDLoc, "immediate operand value out of range");
1885 break;
1886 case Mips::SB16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001887 case Mips::SB16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001888 Opnd = Inst.getOperand(2);
1889 if (!Opnd.isImm())
1890 return Error(IDLoc, "expected immediate operand kind");
1891 Imm = Opnd.getImm();
1892 if (Imm < 0 || Imm > 15)
1893 return Error(IDLoc, "immediate operand value out of range");
1894 break;
1895 case Mips::LHU16_MM:
1896 case Mips::SH16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001897 case Mips::SH16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001898 Opnd = Inst.getOperand(2);
1899 if (!Opnd.isImm())
1900 return Error(IDLoc, "expected immediate operand kind");
1901 Imm = Opnd.getImm();
1902 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1903 return Error(IDLoc, "immediate operand value out of range");
1904 break;
1905 case Mips::LW16_MM:
1906 case Mips::SW16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001907 case Mips::SW16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001908 Opnd = Inst.getOperand(2);
1909 if (!Opnd.isImm())
1910 return Error(IDLoc, "expected immediate operand kind");
1911 Imm = Opnd.getImm();
1912 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1913 return Error(IDLoc, "immediate operand value out of range");
1914 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001915 case Mips::ADDIUPC_MM:
1916 MCOperand Opnd = Inst.getOperand(1);
1917 if (!Opnd.isImm())
1918 return Error(IDLoc, "expected immediate operand kind");
1919 int Imm = Opnd.getImm();
Craig Topper55b1f292015-10-10 20:17:07 +00001920 if ((Imm % 4 != 0) || !isInt<25>(Imm))
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001921 return Error(IDLoc, "immediate operand value out of range");
1922 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001923 }
1924 }
1925
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001926 MacroExpanderResultTy ExpandResult =
1927 tryExpandInstruction(Inst, IDLoc, Instructions);
1928 switch (ExpandResult) {
1929 case MER_NotAMacro:
Jack Carter9e65aa32013-03-22 00:05:30 +00001930 Instructions.push_back(Inst);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001931 break;
1932 case MER_Success:
1933 break;
1934 case MER_Fail:
1935 return true;
1936 }
Jack Carter9e65aa32013-03-22 00:05:30 +00001937
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001938 // If this instruction has a delay slot and .set reorder is active,
1939 // emit a NOP after it.
1940 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
1941 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1942
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001943 if ((Inst.getOpcode() == Mips::JalOneReg ||
1944 Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
1945 isPicAndNotNxxAbi()) {
1946 if (IsCpRestoreSet) {
1947 // We need a NOP between the JALR and the LW:
1948 // If .set reorder has been used, we've already emitted a NOP.
1949 // If .set noreorder has been used, we need to emit a NOP at this point.
1950 if (!AssemblerOptions.back()->isReorder())
1951 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1952
1953 // Load the $gp from the stack.
1954 SmallVector<MCInst, 3> LoadInsts;
1955 createCpRestoreMemOp(true /*IsLoad*/, CpRestoreOffset /*StackOffset*/,
1956 IDLoc, LoadInsts);
1957
1958 for (const MCInst &Inst : LoadInsts)
1959 Instructions.push_back(Inst);
1960
1961 } else
1962 Warning(IDLoc, "no .cprestore used in PIC mode");
1963 }
1964
Jack Carter9e65aa32013-03-22 00:05:30 +00001965 return false;
1966}
1967
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001968MipsAsmParser::MacroExpanderResultTy
1969MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
1970 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001971 switch (Inst.getOpcode()) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001972 default:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001973 return MER_NotAMacro;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001974 case Mips::LoadImm32:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001975 return expandLoadImm(Inst, true, IDLoc, Instructions) ? MER_Fail
1976 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001977 case Mips::LoadImm64:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001978 return expandLoadImm(Inst, false, IDLoc, Instructions) ? MER_Fail
1979 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001980 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001981 case Mips::LoadAddrImm64:
1982 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1983 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
1984 "expected immediate operand kind");
1985
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001986 return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,
1987 Inst.getOperand(1),
1988 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,
1989 Instructions)
1990 ? MER_Fail
1991 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001992 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001993 case Mips::LoadAddrReg64:
1994 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1995 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1996 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
1997 "expected immediate operand kind");
1998
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001999 return expandLoadAddress(Inst.getOperand(0).getReg(),
2000 Inst.getOperand(1).getReg(), Inst.getOperand(2),
2001 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,
2002 Instructions)
2003 ? MER_Fail
2004 : MER_Success;
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002005 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00002006 case Mips::B_MMR6_Pseudo:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002007 return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions) ? MER_Fail
2008 : MER_Success;
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002009 case Mips::SWM_MM:
2010 case Mips::LWM_MM:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002011 return expandLoadStoreMultiple(Inst, IDLoc, Instructions) ? MER_Fail
2012 : MER_Success;
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002013 case Mips::JalOneReg:
2014 case Mips::JalTwoReg:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002015 return expandJalWithRegs(Inst, IDLoc, Instructions) ? MER_Fail
2016 : MER_Success;
Toma Tabacue1e460d2015-06-11 10:36:10 +00002017 case Mips::BneImm:
2018 case Mips::BeqImm:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002019 return expandBranchImm(Inst, IDLoc, Instructions) ? MER_Fail : MER_Success;
Toma Tabacu1a108322015-06-17 13:20:24 +00002020 case Mips::BLT:
2021 case Mips::BLE:
2022 case Mips::BGE:
2023 case Mips::BGT:
2024 case Mips::BLTU:
2025 case Mips::BLEU:
2026 case Mips::BGEU:
2027 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002028 case Mips::BLTL:
2029 case Mips::BLEL:
2030 case Mips::BGEL:
2031 case Mips::BGTL:
2032 case Mips::BLTUL:
2033 case Mips::BLEUL:
2034 case Mips::BGEUL:
2035 case Mips::BGTUL:
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002036 case Mips::BLTImmMacro:
2037 case Mips::BLEImmMacro:
2038 case Mips::BGEImmMacro:
2039 case Mips::BGTImmMacro:
2040 case Mips::BLTUImmMacro:
2041 case Mips::BLEUImmMacro:
2042 case Mips::BGEUImmMacro:
2043 case Mips::BGTUImmMacro:
2044 case Mips::BLTLImmMacro:
2045 case Mips::BLELImmMacro:
2046 case Mips::BGELImmMacro:
2047 case Mips::BGTLImmMacro:
2048 case Mips::BLTULImmMacro:
2049 case Mips::BLEULImmMacro:
2050 case Mips::BGEULImmMacro:
2051 case Mips::BGTULImmMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002052 return expandCondBranches(Inst, IDLoc, Instructions) ? MER_Fail
2053 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002054 case Mips::SDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002055 return expandDiv(Inst, IDLoc, Instructions, false, true) ? MER_Fail
2056 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002057 case Mips::DSDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002058 return expandDiv(Inst, IDLoc, Instructions, true, true) ? MER_Fail
2059 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002060 case Mips::UDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002061 return expandDiv(Inst, IDLoc, Instructions, false, false) ? MER_Fail
2062 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002063 case Mips::DUDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002064 return expandDiv(Inst, IDLoc, Instructions, true, false) ? MER_Fail
2065 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002066 case Mips::PseudoTRUNC_W_S:
2067 return expandTrunc(Inst, false, false, IDLoc, Instructions) ? MER_Fail
2068 : MER_Success;
2069 case Mips::PseudoTRUNC_W_D32:
2070 return expandTrunc(Inst, true, false, IDLoc, Instructions) ? MER_Fail
2071 : MER_Success;
2072 case Mips::PseudoTRUNC_W_D:
2073 return expandTrunc(Inst, true, true, IDLoc, Instructions) ? MER_Fail
2074 : MER_Success;
Daniel Sanders6394ee52015-10-15 14:52:58 +00002075 case Mips::Ulh:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002076 return expandUlh(Inst, true, IDLoc, Instructions) ? MER_Fail : MER_Success;
Toma Tabacud88d79c2015-06-23 14:39:42 +00002077 case Mips::Ulhu:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002078 return expandUlh(Inst, false, IDLoc, Instructions) ? MER_Fail : MER_Success;
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00002079 case Mips::Ulw:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002080 return expandUlw(Inst, IDLoc, Instructions) ? MER_Fail : MER_Success;
2081 case Mips::NORImm:
2082 return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail
2083 : MER_Success;
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002084 case Mips::ADDi:
2085 case Mips::ADDiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002086 case Mips::SLTi:
2087 case Mips::SLTiu:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002088 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2089 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2090 int64_t ImmValue = Inst.getOperand(2).getImm();
2091 if (isInt<16>(ImmValue))
2092 return MER_NotAMacro;
2093 return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail
2094 : MER_Success;
2095 }
2096 return MER_NotAMacro;
2097 case Mips::ANDi:
2098 case Mips::ORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002099 case Mips::XORi:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002100 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2101 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2102 int64_t ImmValue = Inst.getOperand(2).getImm();
2103 if (isUInt<16>(ImmValue))
2104 return MER_NotAMacro;
2105 return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail
2106 : MER_Success;
2107 }
2108 return MER_NotAMacro;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002109 case Mips::ROL:
2110 case Mips::ROR:
2111 return expandRotation(Inst, IDLoc, Instructions) ? MER_Fail
2112 : MER_Success;
2113 case Mips::ROLImm:
2114 case Mips::RORImm:
2115 return expandRotationImm(Inst, IDLoc, Instructions) ? MER_Fail
2116 : MER_Success;
2117 case Mips::DROL:
2118 case Mips::DROR:
2119 return expandDRotation(Inst, IDLoc, Instructions) ? MER_Fail
2120 : MER_Success;
2121 case Mips::DROLImm:
2122 case Mips::DRORImm:
2123 return expandDRotationImm(Inst, IDLoc, Instructions) ? MER_Fail
2124 : MER_Success;
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00002125 case Mips::ABSMacro:
2126 return expandAbs(Inst, IDLoc, Instructions) ? MER_Fail
2127 : MER_Success;
Jack Carterd0bd6422013-04-18 00:41:53 +00002128 }
Jack Carter30a59822012-10-04 04:03:53 +00002129}
Jack Carter92995f12012-10-06 00:53:28 +00002130
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002131bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
2132 SmallVectorImpl<MCInst> &Instructions) {
2133 // Create a JALR instruction which is going to replace the pseudo-JAL.
2134 MCInst JalrInst;
2135 JalrInst.setLoc(IDLoc);
2136 const MCOperand FirstRegOp = Inst.getOperand(0);
2137 const unsigned Opcode = Inst.getOpcode();
2138
2139 if (Opcode == Mips::JalOneReg) {
2140 // jal $rs => jalr $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002141 if (IsCpRestoreSet && inMicroMipsMode()) {
2142 JalrInst.setOpcode(Mips::JALRS16_MM);
2143 JalrInst.addOperand(FirstRegOp);
2144 } else if (inMicroMipsMode()) {
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002145 JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002146 JalrInst.addOperand(FirstRegOp);
2147 } else {
2148 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002149 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002150 JalrInst.addOperand(FirstRegOp);
2151 }
2152 } else if (Opcode == Mips::JalTwoReg) {
2153 // jal $rd, $rs => jalr $rd, $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002154 if (IsCpRestoreSet && inMicroMipsMode())
2155 JalrInst.setOpcode(Mips::JALRS_MM);
2156 else
2157 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002158 JalrInst.addOperand(FirstRegOp);
2159 const MCOperand SecondRegOp = Inst.getOperand(1);
2160 JalrInst.addOperand(SecondRegOp);
2161 }
2162 Instructions.push_back(JalrInst);
2163
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002164 // If .set reorder is active and branch instruction has a delay slot,
2165 // emit a NOP after it.
2166 const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
2167 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) {
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002168 createNop(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc, Instructions);
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002169 }
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002170
2171 return false;
2172}
2173
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002174/// Can the value be represented by a unsigned N-bit value and a shift left?
Benjamin Kramer039b1042015-10-28 13:54:36 +00002175template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002176 unsigned BitNum = findFirstSet(x);
2177
2178 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2179}
2180
2181/// Load (or add) an immediate into a register.
2182///
2183/// @param ImmValue The immediate to load.
2184/// @param DstReg The register that will hold the immediate.
2185/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2186/// for a simple initialization.
2187/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2188/// @param IsAddress True if the immediate represents an address. False if it
2189/// is an integer.
2190/// @param IDLoc Location of the immediate in the source file.
2191/// @param Instructions The instructions emitted by this expansion.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002192bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002193 unsigned SrcReg, bool Is32BitImm,
2194 bool IsAddress, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00002195 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu00e98672015-05-01 12:19:27 +00002196 if (!Is32BitImm && !isGP64bit()) {
2197 Error(IDLoc, "instruction requires a 64-bit architecture");
2198 return true;
2199 }
2200
Daniel Sanders03f9c012015-07-14 12:24:22 +00002201 if (Is32BitImm) {
2202 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2203 // Sign extend up to 64-bit so that the predicates match the hardware
2204 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2205 // true.
2206 ImmValue = SignExtend64<32>(ImmValue);
2207 } else {
2208 Error(IDLoc, "instruction requires a 32-bit immediate");
2209 return true;
2210 }
2211 }
2212
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002213 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2214 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2215
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002216 bool UseSrcReg = false;
2217 if (SrcReg != Mips::NoRegister)
2218 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002219
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002220 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002221 if (UseSrcReg &&
2222 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002223 // At this point we need AT to perform the expansions and we exit if it is
2224 // not available.
2225 unsigned ATReg = getATReg(IDLoc);
2226 if (!ATReg)
2227 return true;
2228 TmpReg = ATReg;
2229 }
2230
Daniel Sanders03f9c012015-07-14 12:24:22 +00002231 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002232 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002233 SrcReg = ZeroReg;
2234
2235 // This doesn't quite follow the usual ABI expectations for N32 but matches
2236 // traditional assembler behaviour. N32 would normally use addiu for both
2237 // integers and addresses.
2238 if (IsAddress && !Is32BitImm) {
2239 emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
2240 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002241 }
2242
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002243 emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
2244 return false;
2245 }
2246
2247 if (isUInt<16>(ImmValue)) {
2248 unsigned TmpReg = DstReg;
2249 if (SrcReg == DstReg) {
2250 TmpReg = getATReg(IDLoc);
2251 if (!TmpReg)
2252 return true;
2253 }
2254
2255 emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002256 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002257 emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2258 return false;
2259 }
2260
2261 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002262 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002263
Toma Tabacu79588102015-04-29 10:19:56 +00002264 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2265 uint16_t Bits15To0 = ImmValue & 0xffff;
2266
Toma Tabacua3d056f2015-05-15 09:42:11 +00002267 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002268 // Traditional behaviour seems to special case this particular value. It's
2269 // not clear why other masks are handled differently.
2270 if (ImmValue == 0xffffffff) {
Daniel Sandersf1ae3672015-08-18 09:55:57 +00002271 emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, Instructions);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002272 emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, Instructions);
2273 if (UseSrcReg)
2274 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2275 return false;
2276 }
2277
2278 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002279 // upper 32 bits.
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002280 emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002281 emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, Instructions);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002282 if (Bits15To0)
2283 emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
2284 if (UseSrcReg)
2285 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2286 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002287 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002288
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002289 emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, Instructions);
2290 if (Bits15To0)
2291 emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002292 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002293 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2294 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002295 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002296
2297 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2298 if (Is32BitImm) {
2299 Error(IDLoc, "instruction requires a 32-bit immediate");
2300 return true;
2301 }
2302
2303 // Traditionally, these immediates are shifted as little as possible and as
2304 // such we align the most significant bit to bit 15 of our temporary.
2305 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2306 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2307 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2308 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
2309 emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, Instructions);
2310 emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, Instructions);
2311
2312 if (UseSrcReg)
2313 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2314
2315 return false;
2316 }
2317
2318 warnIfNoMacro(IDLoc);
2319
2320 // The remaining case is packed with a sequence of dsll and ori with zeros
2321 // being omitted and any neighbouring dsll's being coalesced.
2322 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2323
2324 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2325 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
2326 IDLoc, Instructions))
2327 return false;
2328
2329 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2330 // skip it and defer the shift to the next chunk.
2331 unsigned ShiftCarriedForwards = 16;
2332 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2333 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2334
2335 if (ImmChunk != 0) {
2336 emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
2337 Instructions);
2338 emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, Instructions);
2339 ShiftCarriedForwards = 0;
2340 }
2341
2342 ShiftCarriedForwards += 16;
2343 }
2344 ShiftCarriedForwards -= 16;
2345
2346 // Finish any remaining shifts left by trailing zeros.
2347 if (ShiftCarriedForwards)
2348 emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
2349 Instructions);
2350
2351 if (UseSrcReg)
2352 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2353
Matheus Almeida3813d572014-06-19 14:39:14 +00002354 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002355}
Jack Carter92995f12012-10-06 00:53:28 +00002356
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002357bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
2358 SmallVectorImpl<MCInst> &Instructions) {
2359 const MCOperand &ImmOp = Inst.getOperand(1);
2360 assert(ImmOp.isImm() && "expected immediate operand kind");
2361 const MCOperand &DstRegOp = Inst.getOperand(0);
2362 assert(DstRegOp.isReg() && "expected register operand kind");
2363
2364 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002365 Is32BitImm, false, IDLoc, Instructions))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002366 return true;
2367
2368 return false;
2369}
2370
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002371bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2372 const MCOperand &Offset,
2373 bool Is32BitAddress, SMLoc IDLoc,
2374 SmallVectorImpl<MCInst> &Instructions) {
2375 // la can't produce a usable address when addresses are 64-bit.
2376 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2377 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2378 // We currently can't do this because we depend on the equality
2379 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2380 Error(IDLoc, "la used to load 64-bit address");
2381 // Continue as if we had 'dla' instead.
2382 Is32BitAddress = false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002383 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002384
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002385 // dla requires 64-bit addresses.
Scott Egerton24557012016-01-21 15:11:01 +00002386 if (!Is32BitAddress && !hasMips3()) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002387 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002388 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002389 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002390
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002391 if (!Offset.isImm())
2392 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
2393 Is32BitAddress, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002394
Scott Egerton24557012016-01-21 15:11:01 +00002395 if (!ABI.ArePtrs64bit()) {
2396 // Continue as if we had 'la' whether we had 'la' or 'dla'.
2397 Is32BitAddress = true;
2398 }
2399
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002400 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
2401 IDLoc, Instructions);
Jack Carter543fdf82012-10-09 23:29:45 +00002402}
2403
Toma Tabacuf712ede2015-06-17 14:31:51 +00002404bool MipsAsmParser::loadAndAddSymbolAddress(
2405 const MCExpr *SymExpr, unsigned DstReg, unsigned SrcReg, bool Is32BitSym,
2406 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002407 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002408
Daniel Sandersd5a89412015-10-05 13:19:29 +00002409 const MCExpr *Symbol = cast<MCExpr>(SymExpr);
2410 const MipsMCExpr *HiExpr = MipsMCExpr::create(
2411 MCSymbolRefExpr::VK_Mips_ABS_HI, Symbol, getContext());
2412 const MipsMCExpr *LoExpr = MipsMCExpr::create(
2413 MCSymbolRefExpr::VK_Mips_ABS_LO, Symbol, getContext());
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002414
Toma Tabacufb9d1252015-06-22 12:08:39 +00002415 bool UseSrcReg = SrcReg != Mips::NoRegister;
2416
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002417 // This is the 64-bit symbol address expansion.
2418 if (ABI.ArePtrs64bit() && isGP64bit()) {
2419 // We always need AT for the 64-bit expansion.
2420 // If it is not available we exit.
2421 unsigned ATReg = getATReg(IDLoc);
2422 if (!ATReg)
2423 return true;
2424
Daniel Sandersd5a89412015-10-05 13:19:29 +00002425 const MipsMCExpr *HighestExpr = MipsMCExpr::create(
2426 MCSymbolRefExpr::VK_Mips_HIGHEST, Symbol, getContext());
2427 const MipsMCExpr *HigherExpr = MipsMCExpr::create(
2428 MCSymbolRefExpr::VK_Mips_HIGHER, Symbol, getContext());
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002429
Scott Egerton24557012016-01-21 15:11:01 +00002430 if (UseSrcReg &&
2431 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2432 SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002433 // If $rs is the same as $rd:
2434 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
2435 // daddiu $at, $at, %higher(sym)
2436 // dsll $at, $at, 16
2437 // daddiu $at, $at, %hi(sym)
2438 // dsll $at, $at, 16
2439 // daddiu $at, $at, %lo(sym)
2440 // daddu $rd, $at, $rd
2441 emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
2442 Instructions);
2443 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HigherExpr),
2444 IDLoc, Instructions);
2445 emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
2446 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
2447 Instructions);
2448 emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
2449 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
2450 Instructions);
2451 emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, Instructions);
2452
2453 return false;
2454 }
2455
2456 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2457 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
2458 // lui $at, %hi(sym)
2459 // daddiu $rd, $rd, %higher(sym)
2460 // daddiu $at, $at, %lo(sym)
2461 // dsll32 $rd, $rd, 0
2462 // daddu $rd, $rd, $at
2463 // (daddu $rd, $rd, $rs)
2464 emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
2465 Instructions);
2466 emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
2467 Instructions);
2468 emitRRX(Mips::DADDiu, DstReg, DstReg, MCOperand::createExpr(HigherExpr),
2469 IDLoc, Instructions);
2470 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
2471 Instructions);
2472 emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, Instructions);
2473 emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, Instructions);
2474 if (UseSrcReg)
2475 emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, Instructions);
2476
2477 return false;
2478 }
2479
2480 // And now, the 32-bit symbol address expansion:
2481 // If $rs is the same as $rd:
2482 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
2483 // ori $at, $at, %lo(sym)
2484 // addu $rd, $at, $rd
2485 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2486 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
2487 // ori $rd, $rd, %lo(sym)
2488 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00002489 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002490 if (UseSrcReg &&
2491 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002492 // If $rs is the same as $rd, we need to use AT.
2493 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00002494 unsigned ATReg = getATReg(IDLoc);
2495 if (!ATReg)
2496 return true;
2497 TmpReg = ATReg;
2498 }
2499
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002500 emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, Instructions);
2501 emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr), IDLoc,
2502 Instructions);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002503
Toma Tabacufb9d1252015-06-22 12:08:39 +00002504 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002505 emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2506 else
Scott Egerton24557012016-01-21 15:11:01 +00002507 assert(
2508 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, TmpReg));
Toma Tabacuf712ede2015-06-17 14:31:51 +00002509
Toma Tabacu674825c2015-06-16 12:16:24 +00002510 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002511}
2512
NAKAMURA Takumi2bbc90c2015-01-23 01:02:07 +00002513bool MipsAsmParser::expandUncondBranchMMPseudo(
2514 MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00002515 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
2516 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002517
2518 MCOperand Offset = Inst.getOperand(0);
2519 if (Offset.isExpr()) {
2520 Inst.clear();
2521 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002522 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2523 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2524 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002525 } else {
2526 assert(Offset.isImm() && "expected immediate operand kind");
Craig Topper55b1f292015-10-10 20:17:07 +00002527 if (isInt<11>(Offset.getImm())) {
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002528 // If offset fits into 11 bits then this instruction becomes microMIPS
2529 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00002530 if (inMicroMipsMode())
2531 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002532 } else {
Craig Topper55b1f292015-10-10 20:17:07 +00002533 if (!isInt<17>(Offset.getImm()))
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002534 Error(IDLoc, "branch target out of range");
2535 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
2536 Error(IDLoc, "branch to misaligned address");
2537 Inst.clear();
2538 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002539 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2540 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2541 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002542 }
2543 }
2544 Instructions.push_back(Inst);
2545
Zoran Jovanovicada70912015-09-07 11:56:37 +00002546 // If .set reorder is active and branch instruction has a delay slot,
2547 // emit a NOP after it.
2548 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
2549 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Toma Tabacu234482a2015-03-16 12:03:39 +00002550 createNop(true, IDLoc, Instructions);
2551
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002552 return false;
2553}
2554
Toma Tabacue1e460d2015-06-11 10:36:10 +00002555bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc,
2556 SmallVectorImpl<MCInst> &Instructions) {
2557 const MCOperand &DstRegOp = Inst.getOperand(0);
2558 assert(DstRegOp.isReg() && "expected register operand kind");
2559
2560 const MCOperand &ImmOp = Inst.getOperand(1);
2561 assert(ImmOp.isImm() && "expected immediate operand kind");
2562
2563 const MCOperand &MemOffsetOp = Inst.getOperand(2);
Daniel Sanders90f0d0b2016-02-29 11:24:49 +00002564 assert((MemOffsetOp.isImm() || MemOffsetOp.isExpr()) &&
2565 "expected immediate or expression operand");
Toma Tabacue1e460d2015-06-11 10:36:10 +00002566
2567 unsigned OpCode = 0;
2568 switch(Inst.getOpcode()) {
2569 case Mips::BneImm:
2570 OpCode = Mips::BNE;
2571 break;
2572 case Mips::BeqImm:
2573 OpCode = Mips::BEQ;
2574 break;
2575 default:
2576 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
2577 break;
2578 }
2579
2580 int64_t ImmValue = ImmOp.getImm();
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002581 if (ImmValue == 0)
2582 emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
2583 Instructions);
2584 else {
Toma Tabacue1e460d2015-06-11 10:36:10 +00002585 warnIfNoMacro(IDLoc);
2586
2587 unsigned ATReg = getATReg(IDLoc);
2588 if (!ATReg)
2589 return true;
2590
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002591 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
2592 IDLoc, Instructions))
Toma Tabacue1e460d2015-06-11 10:36:10 +00002593 return true;
2594
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002595 emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, Instructions);
Toma Tabacue1e460d2015-06-11 10:36:10 +00002596 }
2597 return false;
2598}
2599
Jack Carter9e65aa32013-03-22 00:05:30 +00002600void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00002601 SmallVectorImpl<MCInst> &Instructions,
2602 bool isLoad, bool isImmOpnd) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002603 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00002604 const MCExpr *ExprOffset;
2605 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00002606 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002607 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2608 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002609 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002610 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2611 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002612 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00002613 if (isImmOpnd) {
2614 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
2615 ImmOffset = Inst.getOperand(2).getImm();
2616 LoOffset = ImmOffset & 0x0000ffff;
2617 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00002618 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00002619 if (LoOffset & 0x8000)
2620 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00002621 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00002622 ExprOffset = Inst.getOperand(2).getExpr();
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002623 // These are some of the types of expansions we perform here:
2624 // 1) lw $8, sym => lui $8, %hi(sym)
2625 // lw $8, %lo(sym)($8)
2626 // 2) lw $8, offset($9) => lui $8, %hi(offset)
2627 // add $8, $8, $9
2628 // lw $8, %lo(offset)($9)
2629 // 3) lw $8, offset($8) => lui $at, %hi(offset)
2630 // add $at, $at, $8
2631 // lw $8, %lo(offset)($at)
2632 // 4) sw $8, sym => lui $at, %hi(sym)
2633 // sw $8, %lo(sym)($at)
2634 // 5) sw $8, offset($8) => lui $at, %hi(offset)
2635 // add $at, $at, $8
2636 // sw $8, %lo(offset)($at)
2637 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
2638 // ldc1 $f0, %lo(sym)($at)
2639 //
2640 // For load instructions we can use the destination register as a temporary
2641 // if base and dst are different (examples 1 and 2) and if the base register
2642 // is general purpose otherwise we must use $at (example 6) and error if it's
2643 // not available. For stores we must use $at (examples 4 and 5) because we
2644 // must not clobber the source register setting up the offset.
2645 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
2646 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
2647 unsigned RegClassIDOp0 =
2648 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
2649 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
2650 (RegClassIDOp0 == Mips::GPR64RegClassID);
2651 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00002652 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002653 else {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002654 // At this point we need AT to perform the expansions and we exit if it is
2655 // not available.
Toma Tabacu89a712b2015-04-15 10:48:56 +00002656 TmpRegNum = getATReg(IDLoc);
2657 if (!TmpRegNum)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002658 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002659 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002660
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002661 emitRX(Mips::LUi, TmpRegNum,
2662 isImmOpnd ? MCOperand::createImm(HiOffset)
2663 : MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "hi")),
2664 IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00002665 // Add temp register to base.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002666 if (BaseRegNum != Mips::ZERO)
2667 emitRRR(Mips::ADDu, TmpRegNum, TmpRegNum, BaseRegNum, IDLoc, Instructions);
Alp Tokercb402912014-01-24 17:20:08 +00002668 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00002669 // of offset and new base.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002670 emitRRX(Inst.getOpcode(), RegOpNum, TmpRegNum,
2671 isImmOpnd
2672 ? MCOperand::createImm(LoOffset)
2673 : MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "lo")),
2674 IDLoc, Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +00002675}
2676
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002677bool
2678MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2679 SmallVectorImpl<MCInst> &Instructions) {
2680 unsigned OpNum = Inst.getNumOperands();
2681 unsigned Opcode = Inst.getOpcode();
2682 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2683
2684 assert (Inst.getOperand(OpNum - 1).isImm() &&
2685 Inst.getOperand(OpNum - 2).isReg() &&
2686 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2687
2688 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2689 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002690 (Inst.getOperand(OpNum - 2).getReg() == Mips::SP ||
2691 Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) &&
2692 (Inst.getOperand(OpNum - 3).getReg() == Mips::RA ||
2693 Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002694 // It can be implemented as SWM16 or LWM16 instruction.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002695 if (inMicroMipsMode() && hasMips32r6())
2696 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6;
2697 else
2698 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2699 }
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002700
2701 Inst.setOpcode(NewOpcode);
2702 Instructions.push_back(Inst);
2703 return false;
2704}
2705
Toma Tabacu1a108322015-06-17 13:20:24 +00002706bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
2707 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002708 bool EmittedNoMacroWarning = false;
Toma Tabacu1a108322015-06-17 13:20:24 +00002709 unsigned PseudoOpcode = Inst.getOpcode();
2710 unsigned SrcReg = Inst.getOperand(0).getReg();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002711 const MCOperand &TrgOp = Inst.getOperand(1);
Toma Tabacu1a108322015-06-17 13:20:24 +00002712 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
2713
2714 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002715 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00002716
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002717 unsigned TrgReg;
2718 if (TrgOp.isReg())
2719 TrgReg = TrgOp.getReg();
2720 else if (TrgOp.isImm()) {
2721 warnIfNoMacro(IDLoc);
2722 EmittedNoMacroWarning = true;
2723
2724 TrgReg = getATReg(IDLoc);
2725 if (!TrgReg)
2726 return true;
2727
2728 switch(PseudoOpcode) {
2729 default:
2730 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2731 case Mips::BLTImmMacro:
2732 PseudoOpcode = Mips::BLT;
2733 break;
2734 case Mips::BLEImmMacro:
2735 PseudoOpcode = Mips::BLE;
2736 break;
2737 case Mips::BGEImmMacro:
2738 PseudoOpcode = Mips::BGE;
2739 break;
2740 case Mips::BGTImmMacro:
2741 PseudoOpcode = Mips::BGT;
2742 break;
2743 case Mips::BLTUImmMacro:
2744 PseudoOpcode = Mips::BLTU;
2745 break;
2746 case Mips::BLEUImmMacro:
2747 PseudoOpcode = Mips::BLEU;
2748 break;
2749 case Mips::BGEUImmMacro:
2750 PseudoOpcode = Mips::BGEU;
2751 break;
2752 case Mips::BGTUImmMacro:
2753 PseudoOpcode = Mips::BGTU;
2754 break;
2755 case Mips::BLTLImmMacro:
2756 PseudoOpcode = Mips::BLTL;
2757 break;
2758 case Mips::BLELImmMacro:
2759 PseudoOpcode = Mips::BLEL;
2760 break;
2761 case Mips::BGELImmMacro:
2762 PseudoOpcode = Mips::BGEL;
2763 break;
2764 case Mips::BGTLImmMacro:
2765 PseudoOpcode = Mips::BGTL;
2766 break;
2767 case Mips::BLTULImmMacro:
2768 PseudoOpcode = Mips::BLTUL;
2769 break;
2770 case Mips::BLEULImmMacro:
2771 PseudoOpcode = Mips::BLEUL;
2772 break;
2773 case Mips::BGEULImmMacro:
2774 PseudoOpcode = Mips::BGEUL;
2775 break;
2776 case Mips::BGTULImmMacro:
2777 PseudoOpcode = Mips::BGTUL;
2778 break;
2779 }
2780
2781 if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
2782 false, IDLoc, Instructions))
2783 return true;
2784 }
2785
Toma Tabacu1a108322015-06-17 13:20:24 +00002786 switch (PseudoOpcode) {
2787 case Mips::BLT:
2788 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002789 case Mips::BLTL:
2790 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002791 AcceptsEquality = false;
2792 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002793 IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
2794 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002795 ZeroSrcOpcode = Mips::BGTZ;
2796 ZeroTrgOpcode = Mips::BLTZ;
2797 break;
2798 case Mips::BLE:
2799 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002800 case Mips::BLEL:
2801 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002802 AcceptsEquality = true;
2803 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002804 IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
2805 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002806 ZeroSrcOpcode = Mips::BGEZ;
2807 ZeroTrgOpcode = Mips::BLEZ;
2808 break;
2809 case Mips::BGE:
2810 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002811 case Mips::BGEL:
2812 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002813 AcceptsEquality = true;
2814 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002815 IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
2816 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002817 ZeroSrcOpcode = Mips::BLEZ;
2818 ZeroTrgOpcode = Mips::BGEZ;
2819 break;
2820 case Mips::BGT:
2821 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002822 case Mips::BGTL:
2823 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002824 AcceptsEquality = false;
2825 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002826 IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
2827 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002828 ZeroSrcOpcode = Mips::BLTZ;
2829 ZeroTrgOpcode = Mips::BGTZ;
2830 break;
2831 default:
2832 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2833 }
2834
Toma Tabacu1a108322015-06-17 13:20:24 +00002835 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
2836 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
2837 if (IsSrcRegZero && IsTrgRegZero) {
2838 // FIXME: All of these Opcode-specific if's are needed for compatibility
2839 // with GAS' behaviour. However, they may not generate the most efficient
2840 // code in some circumstances.
2841 if (PseudoOpcode == Mips::BLT) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002842 emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2843 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002844 return false;
2845 }
2846 if (PseudoOpcode == Mips::BLE) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002847 emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2848 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002849 Warning(IDLoc, "branch is always taken");
2850 return false;
2851 }
2852 if (PseudoOpcode == Mips::BGE) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002853 emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2854 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002855 Warning(IDLoc, "branch is always taken");
2856 return false;
2857 }
2858 if (PseudoOpcode == Mips::BGT) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002859 emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2860 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002861 return false;
2862 }
2863 if (PseudoOpcode == Mips::BGTU) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002864 emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
2865 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002866 return false;
2867 }
2868 if (AcceptsEquality) {
2869 // If both registers are $0 and the pseudo-branch accepts equality, it
2870 // will always be taken, so we emit an unconditional branch.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002871 emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
2872 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002873 Warning(IDLoc, "branch is always taken");
2874 return false;
2875 }
2876 // If both registers are $0 and the pseudo-branch does not accept
2877 // equality, it will never be taken, so we don't have to emit anything.
2878 return false;
2879 }
2880 if (IsSrcRegZero || IsTrgRegZero) {
2881 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
2882 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
2883 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
2884 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
2885 // the pseudo-branch will never be taken, so we don't emit anything.
2886 // This only applies to unsigned pseudo-branches.
2887 return false;
2888 }
2889 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
2890 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
2891 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
2892 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
2893 // the pseudo-branch will always be taken, so we emit an unconditional
2894 // branch.
2895 // This only applies to unsigned pseudo-branches.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002896 emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
2897 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002898 Warning(IDLoc, "branch is always taken");
2899 return false;
2900 }
2901 if (IsUnsigned) {
2902 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
2903 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
2904 // the pseudo-branch will be taken only when the non-zero register is
2905 // different from 0, so we emit a BNEZ.
2906 //
2907 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
2908 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
2909 // the pseudo-branch will be taken only when the non-zero register is
2910 // equal to 0, so we emit a BEQZ.
2911 //
2912 // Because only BLEU and BGEU branch on equality, we can use the
2913 // AcceptsEquality variable to decide when to emit the BEQZ.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002914 emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
2915 IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
2916 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002917 return false;
2918 }
2919 // If we have a signed pseudo-branch and one of the registers is $0,
2920 // we can use an appropriate compare-to-zero branch. We select which one
2921 // to use in the switch statement above.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002922 emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
2923 IsSrcRegZero ? TrgReg : SrcReg, MCOperand::createExpr(OffsetExpr),
2924 IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002925 return false;
2926 }
2927
2928 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
2929 // expansions. If it is not available, we return.
2930 unsigned ATRegNum = getATReg(IDLoc);
2931 if (!ATRegNum)
2932 return true;
2933
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002934 if (!EmittedNoMacroWarning)
2935 warnIfNoMacro(IDLoc);
Toma Tabacu1a108322015-06-17 13:20:24 +00002936
2937 // SLT fits well with 2 of our 4 pseudo-branches:
2938 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
2939 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
2940 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
2941 // This is accomplished by using a BNEZ with the result of the SLT.
2942 //
2943 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
2944 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
2945 // Because only BGE and BLE branch on equality, we can use the
2946 // AcceptsEquality variable to decide when to emit the BEQZ.
2947 // Note that the order of the SLT arguments doesn't change between
2948 // opposites.
2949 //
2950 // The same applies to the unsigned variants, except that SLTu is used
2951 // instead of SLT.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002952 emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
2953 ReverseOrderSLT ? TrgReg : SrcReg, ReverseOrderSLT ? SrcReg : TrgReg,
2954 IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002955
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002956 emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
2957 : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
2958 ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2959 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002960 return false;
2961}
2962
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002963bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc,
2964 SmallVectorImpl<MCInst> &Instructions,
2965 const bool IsMips64, const bool Signed) {
2966 if (hasMips32r6()) {
2967 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
2968 return false;
2969 }
2970
2971 warnIfNoMacro(IDLoc);
2972
2973 const MCOperand &RsRegOp = Inst.getOperand(0);
2974 assert(RsRegOp.isReg() && "expected register operand kind");
2975 unsigned RsReg = RsRegOp.getReg();
2976
2977 const MCOperand &RtRegOp = Inst.getOperand(1);
2978 assert(RtRegOp.isReg() && "expected register operand kind");
2979 unsigned RtReg = RtRegOp.getReg();
2980 unsigned DivOp;
2981 unsigned ZeroReg;
2982
2983 if (IsMips64) {
2984 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
2985 ZeroReg = Mips::ZERO_64;
2986 } else {
2987 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
2988 ZeroReg = Mips::ZERO;
2989 }
2990
2991 bool UseTraps = useTraps();
2992
2993 if (RsReg == Mips::ZERO || RsReg == Mips::ZERO_64) {
2994 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)
2995 Warning(IDLoc, "dividing zero by zero");
2996 if (IsMips64) {
2997 if (Signed && (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)) {
2998 if (UseTraps) {
2999 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
3000 return false;
3001 }
3002
3003 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
3004 return false;
3005 }
3006 } else {
3007 emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
3008 return false;
3009 }
3010 }
3011
3012 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
3013 Warning(IDLoc, "division by zero");
3014 if (Signed) {
3015 if (UseTraps) {
3016 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
3017 return false;
3018 }
3019
3020 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
3021 return false;
3022 }
3023 }
3024
3025 // FIXME: The values for these two BranchTarget variables may be different in
3026 // micromips. These magic numbers need to be removed.
3027 unsigned BranchTargetNoTraps;
3028 unsigned BranchTarget;
3029
3030 if (UseTraps) {
3031 BranchTarget = IsMips64 ? 12 : 8;
3032 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
3033 } else {
3034 BranchTarget = IsMips64 ? 20 : 16;
3035 BranchTargetNoTraps = 8;
3036 // Branch to the li instruction.
3037 emitRRI(Mips::BNE, RtReg, ZeroReg, BranchTargetNoTraps, IDLoc,
3038 Instructions);
3039 }
3040
3041 emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
3042
3043 if (!UseTraps)
3044 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
3045
3046 if (!Signed) {
3047 emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
3048 return false;
3049 }
3050
3051 unsigned ATReg = getATReg(IDLoc);
3052 if (!ATReg)
3053 return true;
3054
3055 emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, Instructions);
3056 if (IsMips64) {
3057 // Branch to the mflo instruction.
3058 emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
3059 emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, Instructions);
3060 emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, Instructions);
3061 } else {
3062 // Branch to the mflo instruction.
3063 emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
3064 emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, Instructions);
3065 }
3066
3067 if (UseTraps)
3068 emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, Instructions);
3069 else {
3070 // Branch to the mflo instruction.
3071 emitRRI(Mips::BNE, RsReg, ATReg, BranchTargetNoTraps, IDLoc, Instructions);
3072 emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, Instructions);
3073 emitII(Mips::BREAK, 0x6, 0, IDLoc, Instructions);
3074 }
3075 emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
3076 return false;
3077}
3078
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003079bool MipsAsmParser::expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU,
3080 SMLoc IDLoc,
3081 SmallVectorImpl<MCInst> &Instructions) {
3082
3083 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
3084 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() &&
3085 Inst.getOperand(2).isReg() && "Invalid instruction operand.");
3086
3087 unsigned FirstReg = Inst.getOperand(0).getReg();
3088 unsigned SecondReg = Inst.getOperand(1).getReg();
3089 unsigned ThirdReg = Inst.getOperand(2).getReg();
3090
3091 if (hasMips1() && !hasMips2()) {
3092 unsigned ATReg = getATReg(IDLoc);
3093 if (!ATReg)
3094 return true;
3095 emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, Instructions);
3096 emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, Instructions);
3097 createNop(false, IDLoc, Instructions);
3098 emitRRI(Mips::ORi, ATReg, ThirdReg, 0x3, IDLoc, Instructions);
3099 emitRRI(Mips::XORi, ATReg, ATReg, 0x2, IDLoc, Instructions);
3100 emitRR(Mips::CTC1, Mips::RA, ATReg, IDLoc, Instructions);
3101 createNop(false, IDLoc, Instructions);
3102 emitRR(IsDouble ? (Is64FPU ? Mips::CVT_W_D64 : Mips::CVT_W_D32)
3103 : Mips::CVT_W_S,
3104 FirstReg, SecondReg, IDLoc, Instructions);
3105 emitRR(Mips::CTC1, Mips::RA, ThirdReg, IDLoc, Instructions);
3106 createNop(false, IDLoc, Instructions);
3107 return false;
3108 }
3109
3110 emitRR(IsDouble ? (Is64FPU ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32)
3111 : Mips::TRUNC_W_S,
3112 FirstReg, SecondReg, IDLoc, Instructions);
3113
3114 return false;
3115}
3116
Daniel Sanders6394ee52015-10-15 14:52:58 +00003117bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
3118 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacud88d79c2015-06-23 14:39:42 +00003119 if (hasMips32r6() || hasMips64r6()) {
3120 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3121 return false;
3122 }
3123
3124 warnIfNoMacro(IDLoc);
3125
3126 const MCOperand &DstRegOp = Inst.getOperand(0);
3127 assert(DstRegOp.isReg() && "expected register operand kind");
3128
3129 const MCOperand &SrcRegOp = Inst.getOperand(1);
3130 assert(SrcRegOp.isReg() && "expected register operand kind");
3131
3132 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3133 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3134
3135 unsigned DstReg = DstRegOp.getReg();
3136 unsigned SrcReg = SrcRegOp.getReg();
3137 int64_t OffsetValue = OffsetImmOp.getImm();
3138
3139 // NOTE: We always need AT for ULHU, as it is always used as the source
3140 // register for one of the LBu's.
3141 unsigned ATReg = getATReg(IDLoc);
3142 if (!ATReg)
3143 return true;
3144
3145 // When the value of offset+1 does not fit in 16 bits, we have to load the
3146 // offset in AT, (D)ADDu the original source register (if there was one), and
3147 // then use AT as the source register for the 2 generated LBu's.
3148 bool LoadedOffsetInAT = false;
3149 if (!isInt<16>(OffsetValue + 1) || !isInt<16>(OffsetValue)) {
3150 LoadedOffsetInAT = true;
3151
3152 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003153 true, IDLoc, Instructions))
Toma Tabacud88d79c2015-06-23 14:39:42 +00003154 return true;
3155
3156 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3157 // because it will make our output more similar to GAS'. For example,
3158 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3159 // instead of just an "ori $1, $9, 32768".
3160 // NOTE: If there is no source register specified in the ULHU, the parser
3161 // will interpret it as $0.
3162 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
3163 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
3164 }
3165
3166 unsigned FirstLbuDstReg = LoadedOffsetInAT ? DstReg : ATReg;
3167 unsigned SecondLbuDstReg = LoadedOffsetInAT ? ATReg : DstReg;
3168 unsigned LbuSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3169
3170 int64_t FirstLbuOffset = 0, SecondLbuOffset = 0;
3171 if (isLittle()) {
3172 FirstLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3173 SecondLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3174 } else {
3175 FirstLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3176 SecondLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3177 }
3178
3179 unsigned SllReg = LoadedOffsetInAT ? DstReg : ATReg;
3180
Daniel Sanders6394ee52015-10-15 14:52:58 +00003181 emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
3182 FirstLbuOffset, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003183
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003184 emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondLbuOffset, IDLoc,
3185 Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003186
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003187 emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003188
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003189 emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003190
3191 return false;
3192}
3193
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003194bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc,
3195 SmallVectorImpl<MCInst> &Instructions) {
3196 if (hasMips32r6() || hasMips64r6()) {
3197 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3198 return false;
3199 }
3200
3201 const MCOperand &DstRegOp = Inst.getOperand(0);
3202 assert(DstRegOp.isReg() && "expected register operand kind");
3203
3204 const MCOperand &SrcRegOp = Inst.getOperand(1);
3205 assert(SrcRegOp.isReg() && "expected register operand kind");
3206
3207 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3208 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3209
3210 unsigned SrcReg = SrcRegOp.getReg();
3211 int64_t OffsetValue = OffsetImmOp.getImm();
3212 unsigned ATReg = 0;
3213
3214 // When the value of offset+3 does not fit in 16 bits, we have to load the
3215 // offset in AT, (D)ADDu the original source register (if there was one), and
3216 // then use AT as the source register for the generated LWL and LWR.
3217 bool LoadedOffsetInAT = false;
3218 if (!isInt<16>(OffsetValue + 3) || !isInt<16>(OffsetValue)) {
3219 ATReg = getATReg(IDLoc);
3220 if (!ATReg)
3221 return true;
3222 LoadedOffsetInAT = true;
3223
3224 warnIfNoMacro(IDLoc);
3225
3226 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003227 true, IDLoc, Instructions))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003228 return true;
3229
3230 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3231 // because it will make our output more similar to GAS'. For example,
3232 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3233 // instead of just an "ori $1, $9, 32768".
3234 // NOTE: If there is no source register specified in the ULW, the parser
3235 // will interpret it as $0.
3236 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
3237 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
3238 }
3239
3240 unsigned FinalSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3241 int64_t LeftLoadOffset = 0, RightLoadOffset = 0;
3242 if (isLittle()) {
3243 LeftLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3244 RightLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3245 } else {
3246 LeftLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3247 RightLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3248 }
3249
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003250 emitRRI(Mips::LWL, DstRegOp.getReg(), FinalSrcReg, LeftLoadOffset, IDLoc,
3251 Instructions);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003252
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003253 emitRRI(Mips::LWR, DstRegOp.getReg(), FinalSrcReg, RightLoadOffset, IDLoc,
3254 Instructions);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003255
3256 return false;
3257}
3258
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003259bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
3260 SmallVectorImpl<MCInst> &Instructions) {
3261
3262 assert (Inst.getNumOperands() == 3 && "Invalid operand count");
3263 assert (Inst.getOperand(0).isReg() &&
3264 Inst.getOperand(1).isReg() &&
3265 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
3266
3267 unsigned ATReg = Mips::NoRegister;
3268 unsigned FinalDstReg = Mips::NoRegister;
3269 unsigned DstReg = Inst.getOperand(0).getReg();
3270 unsigned SrcReg = Inst.getOperand(1).getReg();
3271 int64_t ImmValue = Inst.getOperand(2).getImm();
3272
3273 bool Is32Bit = isInt<32>(ImmValue) || isUInt<32>(ImmValue);
3274
3275 unsigned FinalOpcode = Inst.getOpcode();
3276
3277 if (DstReg == SrcReg) {
3278 ATReg = getATReg(Inst.getLoc());
3279 if (!ATReg)
3280 return true;
3281 FinalDstReg = DstReg;
3282 DstReg = ATReg;
3283 }
3284
3285 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Instructions)) {
3286 switch (FinalOpcode) {
3287 default:
3288 llvm_unreachable("unimplemented expansion");
3289 case (Mips::ADDi):
3290 FinalOpcode = Mips::ADD;
3291 break;
3292 case (Mips::ADDiu):
3293 FinalOpcode = Mips::ADDu;
3294 break;
3295 case (Mips::ANDi):
3296 FinalOpcode = Mips::AND;
3297 break;
3298 case (Mips::NORImm):
3299 FinalOpcode = Mips::NOR;
3300 break;
3301 case (Mips::ORi):
3302 FinalOpcode = Mips::OR;
3303 break;
3304 case (Mips::SLTi):
3305 FinalOpcode = Mips::SLT;
3306 break;
3307 case (Mips::SLTiu):
3308 FinalOpcode = Mips::SLTu;
3309 break;
3310 case (Mips::XORi):
3311 FinalOpcode = Mips::XOR;
3312 break;
3313 }
3314
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003315 if (FinalDstReg == Mips::NoRegister)
3316 emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, Instructions);
3317 else
3318 emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc,
3319 Instructions);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003320 return false;
3321 }
3322 return true;
3323}
3324
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003325bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc,
3326 SmallVectorImpl<MCInst> &Instructions) {
3327 unsigned ATReg = Mips::NoRegister;
3328 unsigned DReg = Inst.getOperand(0).getReg();
3329 unsigned SReg = Inst.getOperand(1).getReg();
3330 unsigned TReg = Inst.getOperand(2).getReg();
3331 unsigned TmpReg = DReg;
3332
3333 unsigned FirstShift = Mips::NOP;
3334 unsigned SecondShift = Mips::NOP;
3335
3336 if (hasMips32r2()) {
3337
3338 if (DReg == SReg) {
3339 TmpReg = getATReg(Inst.getLoc());
3340 if (!TmpReg)
3341 return true;
3342 }
3343
3344 if (Inst.getOpcode() == Mips::ROL) {
3345 emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions);
3346 emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), Instructions);
3347 return false;
3348 }
3349
3350 if (Inst.getOpcode() == Mips::ROR) {
3351 emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), Instructions);
3352 return false;
3353 }
3354
3355 return true;
3356 }
3357
3358 if (hasMips32()) {
3359
3360 switch (Inst.getOpcode()) {
3361 default:
3362 llvm_unreachable("unexpected instruction opcode");
3363 case Mips::ROL:
3364 FirstShift = Mips::SRLV;
3365 SecondShift = Mips::SLLV;
3366 break;
3367 case Mips::ROR:
3368 FirstShift = Mips::SLLV;
3369 SecondShift = Mips::SRLV;
3370 break;
3371 }
3372
3373 ATReg = getATReg(Inst.getLoc());
3374 if (!ATReg)
3375 return true;
3376
3377 emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions);
3378 emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), Instructions);
3379 emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), Instructions);
3380 emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions);
3381
3382 return false;
3383 }
3384
3385 return true;
3386}
3387
3388bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
3389 SmallVectorImpl<MCInst> &Instructions) {
3390
3391 unsigned ATReg = Mips::NoRegister;
3392 unsigned DReg = Inst.getOperand(0).getReg();
3393 unsigned SReg = Inst.getOperand(1).getReg();
3394 int64_t ImmValue = Inst.getOperand(2).getImm();
3395
3396 unsigned FirstShift = Mips::NOP;
3397 unsigned SecondShift = Mips::NOP;
3398
3399 if (hasMips32r2()) {
3400
3401 if (Inst.getOpcode() == Mips::ROLImm) {
3402 uint64_t MaxShift = 32;
3403 uint64_t ShiftValue = ImmValue;
3404 if (ImmValue != 0)
3405 ShiftValue = MaxShift - ImmValue;
3406 emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), Instructions);
3407 return false;
3408 }
3409
3410 if (Inst.getOpcode() == Mips::RORImm) {
3411 emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), Instructions);
3412 return false;
3413 }
3414
3415 return true;
3416 }
3417
3418 if (hasMips32()) {
3419
3420 if (ImmValue == 0) {
3421 emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), Instructions);
3422 return false;
3423 }
3424
3425 switch (Inst.getOpcode()) {
3426 default:
3427 llvm_unreachable("unexpected instruction opcode");
3428 case Mips::ROLImm:
3429 FirstShift = Mips::SLL;
3430 SecondShift = Mips::SRL;
3431 break;
3432 case Mips::RORImm:
3433 FirstShift = Mips::SRL;
3434 SecondShift = Mips::SLL;
3435 break;
3436 }
3437
3438 ATReg = getATReg(Inst.getLoc());
3439 if (!ATReg)
3440 return true;
3441
3442 emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), Instructions);
3443 emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), Instructions);
3444 emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions);
3445
3446 return false;
3447 }
3448
3449 return true;
3450}
3451
3452bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc,
3453 SmallVectorImpl<MCInst> &Instructions) {
3454
3455 unsigned ATReg = Mips::NoRegister;
3456 unsigned DReg = Inst.getOperand(0).getReg();
3457 unsigned SReg = Inst.getOperand(1).getReg();
3458 unsigned TReg = Inst.getOperand(2).getReg();
3459 unsigned TmpReg = DReg;
3460
3461 unsigned FirstShift = Mips::NOP;
3462 unsigned SecondShift = Mips::NOP;
3463
3464 if (hasMips64r2()) {
3465
3466 if (TmpReg == SReg) {
3467 TmpReg = getATReg(Inst.getLoc());
3468 if (!TmpReg)
3469 return true;
3470 }
3471
3472 if (Inst.getOpcode() == Mips::DROL) {
3473 emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions);
3474 emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), Instructions);
3475 return false;
3476 }
3477
3478 if (Inst.getOpcode() == Mips::DROR) {
3479 emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), Instructions);
3480 return false;
3481 }
3482
3483 return true;
3484 }
3485
3486 if (hasMips64()) {
3487
3488 switch (Inst.getOpcode()) {
3489 default:
3490 llvm_unreachable("unexpected instruction opcode");
3491 case Mips::DROL:
3492 FirstShift = Mips::DSRLV;
3493 SecondShift = Mips::DSLLV;
3494 break;
3495 case Mips::DROR:
3496 FirstShift = Mips::DSLLV;
3497 SecondShift = Mips::DSRLV;
3498 break;
3499 }
3500
3501 ATReg = getATReg(Inst.getLoc());
3502 if (!ATReg)
3503 return true;
3504
3505 emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions);
3506 emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), Instructions);
3507 emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), Instructions);
3508 emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions);
3509
3510 return false;
3511 }
3512
3513 return true;
3514}
3515
3516bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
3517 SmallVectorImpl<MCInst> &Instructions) {
3518
3519 unsigned ATReg = Mips::NoRegister;
3520 unsigned DReg = Inst.getOperand(0).getReg();
3521 unsigned SReg = Inst.getOperand(1).getReg();
3522 int64_t ImmValue = Inst.getOperand(2).getImm() % 64;
3523
3524 unsigned FirstShift = Mips::NOP;
3525 unsigned SecondShift = Mips::NOP;
3526
3527 MCInst TmpInst;
3528
3529 if (hasMips64r2()) {
3530
3531 unsigned FinalOpcode = Mips::NOP;
3532 if (ImmValue == 0)
3533 FinalOpcode = Mips::DROTR;
3534 else if (ImmValue % 32 == 0)
3535 FinalOpcode = Mips::DROTR32;
3536 else if ((ImmValue >= 1) && (ImmValue <= 32)) {
3537 if (Inst.getOpcode() == Mips::DROLImm)
3538 FinalOpcode = Mips::DROTR32;
3539 else
3540 FinalOpcode = Mips::DROTR;
3541 } else if (ImmValue >= 33) {
3542 if (Inst.getOpcode() == Mips::DROLImm)
3543 FinalOpcode = Mips::DROTR;
3544 else
3545 FinalOpcode = Mips::DROTR32;
3546 }
3547
3548 uint64_t ShiftValue = ImmValue % 32;
3549 if (Inst.getOpcode() == Mips::DROLImm)
3550 ShiftValue = (32 - ImmValue % 32) % 32;
3551
3552 emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), Instructions);
3553
3554 return false;
3555 }
3556
3557 if (hasMips64()) {
3558
3559 if (ImmValue == 0) {
3560 emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), Instructions);
3561 return false;
3562 }
3563
3564 switch (Inst.getOpcode()) {
3565 default:
3566 llvm_unreachable("unexpected instruction opcode");
3567 case Mips::DROLImm:
3568 if ((ImmValue >= 1) && (ImmValue <= 31)) {
3569 FirstShift = Mips::DSLL;
3570 SecondShift = Mips::DSRL32;
3571 }
3572 if (ImmValue == 32) {
3573 FirstShift = Mips::DSLL32;
3574 SecondShift = Mips::DSRL32;
3575 }
3576 if ((ImmValue >= 33) && (ImmValue <= 63)) {
3577 FirstShift = Mips::DSLL32;
3578 SecondShift = Mips::DSRL;
3579 }
3580 break;
3581 case Mips::DRORImm:
3582 if ((ImmValue >= 1) && (ImmValue <= 31)) {
3583 FirstShift = Mips::DSRL;
3584 SecondShift = Mips::DSLL32;
3585 }
3586 if (ImmValue == 32) {
3587 FirstShift = Mips::DSRL32;
3588 SecondShift = Mips::DSLL32;
3589 }
3590 if ((ImmValue >= 33) && (ImmValue <= 63)) {
3591 FirstShift = Mips::DSRL32;
3592 SecondShift = Mips::DSLL;
3593 }
3594 break;
3595 }
3596
3597 ATReg = getATReg(Inst.getLoc());
3598 if (!ATReg)
3599 return true;
3600
3601 emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), Instructions);
3602 emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32, Inst.getLoc(), Instructions);
3603 emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions);
3604
3605 return false;
3606 }
3607
3608 return true;
3609}
3610
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003611bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc,
3612 SmallVectorImpl<MCInst> &Instructions) {
3613
3614 unsigned FirstRegOp = Inst.getOperand(0).getReg();
3615 unsigned SecondRegOp = Inst.getOperand(1).getReg();
3616
3617 emitRI(Mips::BGEZ, SecondRegOp, 8, IDLoc, Instructions);
3618 if (FirstRegOp != SecondRegOp)
3619 emitRRR(Mips::ADDu, FirstRegOp, SecondRegOp, Mips::ZERO, IDLoc, Instructions);
3620 else
3621 createNop(false, IDLoc, Instructions);
3622 emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, Instructions);
3623
3624 return false;
3625}
3626
Toma Tabacu234482a2015-03-16 12:03:39 +00003627void MipsAsmParser::createNop(bool hasShortDelaySlot, SMLoc IDLoc,
3628 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003629 if (hasShortDelaySlot)
3630 emitRR(Mips::MOVE16_MM, Mips::ZERO, Mips::ZERO, IDLoc, Instructions);
3631 else
3632 emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, Instructions);
Toma Tabacu234482a2015-03-16 12:03:39 +00003633}
3634
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003635void MipsAsmParser::createAddu(unsigned DstReg, unsigned SrcReg,
Toma Tabacu0b3e9782015-06-23 14:00:54 +00003636 unsigned TrgReg, bool Is64Bit,
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003637 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanders03f9c012015-07-14 12:24:22 +00003638 emitRRR(Is64Bit ? Mips::DADDu : Mips::ADDu, DstReg, SrcReg, TrgReg, SMLoc(),
3639 Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003640}
3641
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003642void MipsAsmParser::createCpRestoreMemOp(
3643 bool IsLoad, int StackOffset, SMLoc IDLoc,
3644 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003645 // If the offset can not fit into 16 bits, we need to expand.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003646 if (!isInt<16>(StackOffset)) {
3647 MCInst MemInst;
3648 MemInst.setOpcode(IsLoad ? Mips::LW : Mips::SW);
3649 MemInst.addOperand(MCOperand::createReg(Mips::GP));
3650 MemInst.addOperand(MCOperand::createReg(Mips::SP));
3651 MemInst.addOperand(MCOperand::createImm(StackOffset));
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003652 expandMemInst(MemInst, IDLoc, Instructions, IsLoad, true /*HasImmOpnd*/);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003653 return;
3654 }
3655
3656 emitRRI(IsLoad ? Mips::LW : Mips::SW, Mips::GP, Mips::SP, StackOffset, IDLoc,
3657 Instructions);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003658}
3659
Matheus Almeida595fcab2014-06-11 15:05:56 +00003660unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
3661 // As described by the Mips32r2 spec, the registers Rd and Rs for
3662 // jalr.hb must be different.
3663 unsigned Opcode = Inst.getOpcode();
3664
3665 if (Opcode == Mips::JALR_HB &&
3666 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
3667 return Match_RequiresDifferentSrcAndDst;
3668
3669 return Match_Success;
3670}
3671
Daniel Sanders52da7af2015-11-06 12:11:03 +00003672static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
3673 uint64_t ErrorInfo) {
3674 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
3675 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
3676 if (ErrorLoc == SMLoc())
3677 return Loc;
3678 return ErrorLoc;
3679 }
3680 return Loc;
3681}
3682
David Blaikie960ea3f2014-06-08 16:18:35 +00003683bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3684 OperandVector &Operands,
3685 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003686 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00003687 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00003688
Jack Carterb4dbc172012-09-05 23:34:03 +00003689 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00003690 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00003691 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003692 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00003693
3694 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003695 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003696 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00003697 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00003698 for (unsigned i = 0; i < Instructions.size(); i++)
Akira Hatanakabd9fc282015-11-14 05:20:05 +00003699 Out.EmitInstruction(Instructions[i], getSTI());
Jack Carterb4dbc172012-09-05 23:34:03 +00003700 return false;
3701 }
3702 case Match_MissingFeature:
3703 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
3704 return true;
3705 case Match_InvalidOperand: {
3706 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00003707 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003708 if (ErrorInfo >= Operands.size())
3709 return Error(IDLoc, "too few operands for instruction");
3710
Daniel Sanders52da7af2015-11-06 12:11:03 +00003711 ErrorLoc = Operands[ErrorInfo]->getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00003712 if (ErrorLoc == SMLoc())
3713 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00003714 }
3715
3716 return Error(ErrorLoc, "invalid operand for instruction");
3717 }
3718 case Match_MnemonicFail:
3719 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00003720 case Match_RequiresDifferentSrcAndDst:
3721 return Error(IDLoc, "source and destination must be different");
Daniel Sanders52da7af2015-11-06 12:11:03 +00003722 case Match_Immz:
3723 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00003724 case Match_UImm1_0:
3725 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3726 "expected 1-bit unsigned immediate");
Daniel Sandersea4f6532015-11-06 12:22:31 +00003727 case Match_UImm2_0:
3728 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3729 "expected 2-bit unsigned immediate");
3730 case Match_UImm2_1:
3731 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3732 "expected immediate in range 1 .. 4");
Daniel Sanders38ce0f62015-11-06 12:31:27 +00003733 case Match_UImm3_0:
3734 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3735 "expected 3-bit unsigned immediate");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00003736 case Match_UImm4_0:
3737 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3738 "expected 4-bit unsigned immediate");
Daniel Sanders78e89022016-03-11 11:37:50 +00003739 case Match_SImm4_0:
3740 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3741 "expected 4-bit signed immediate");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00003742 case Match_UImm5_0:
3743 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3744 "expected 5-bit unsigned immediate");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00003745 case Match_UImm5_1:
3746 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3747 "expected immediate in range 1 .. 32");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00003748 case Match_UImm5_32:
3749 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3750 "expected immediate in range 32 .. 63");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00003751 case Match_UImm5_33:
3752 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3753 "expected immediate in range 33 .. 64");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00003754 case Match_UImm5_0_Report_UImm6:
3755 // This is used on UImm5 operands that have a corresponding UImm5_32
3756 // operand to avoid confusing the user.
3757 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3758 "expected 6-bit unsigned immediate");
3759 case Match_UImm5_Lsl2:
3760 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3761 "expected both 7-bit unsigned immediate and multiple of 4");
Hrvoje Varga46458d02016-02-25 12:53:29 +00003762 case Match_UImmRange2_64:
3763 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3764 "expected immediate in range 2 .. 64");
Daniel Sanders59d092f2015-12-08 13:49:19 +00003765 case Match_UImm6_0:
3766 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3767 "expected 6-bit unsigned immediate");
Daniel Sanders78e89022016-03-11 11:37:50 +00003768 case Match_SImm6_0:
Zlatko Buljan252cca52015-12-18 08:59:37 +00003769 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3770 "expected 6-bit signed immediate");
3771 case Match_UImm7_0:
3772 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3773 "expected 7-bit unsigned immediate");
Daniel Sanders106d2d42015-12-08 14:42:10 +00003774 case Match_UImm8_0:
3775 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3776 "expected 8-bit unsigned immediate");
Daniel Sanders3c722312015-12-09 13:48:05 +00003777 case Match_UImm10_0:
3778 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3779 "expected 10-bit unsigned immediate");
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00003780 case Match_UImm16:
3781 case Match_UImm16_Relaxed:
3782 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3783 "expected 16-bit unsigned immediate");
Daniel Sanders03a8d2f2016-02-29 16:06:38 +00003784 case Match_UImm20_0:
3785 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3786 "expected 20-bit unsigned immediate");
Jack Carterb4dbc172012-09-05 23:34:03 +00003787 }
Craig Topper589ceee2015-01-03 08:16:34 +00003788
3789 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00003790}
3791
Toma Tabacud9d344b2015-04-27 14:05:04 +00003792void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
3793 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
3794 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
3795 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003796}
3797
Toma Tabacu81496c12015-05-20 08:54:45 +00003798void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
3799 if (!AssemblerOptions.back()->isMacro())
3800 Warning(Loc, "macro instruction expanded into multiple instructions");
3801}
3802
Daniel Sandersef638fe2014-10-03 15:37:37 +00003803void
3804MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
3805 SMRange Range, bool ShowColors) {
3806 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00003807 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00003808 ShowColors);
3809}
3810
Jack Carter1ac53222013-02-20 23:11:17 +00003811int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003812 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003813
Vladimir Medic4c299852013-11-06 11:27:05 +00003814 CC = StringSwitch<unsigned>(Name)
3815 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003816 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00003817 .Case("a0", 4)
3818 .Case("a1", 5)
3819 .Case("a2", 6)
3820 .Case("a3", 7)
3821 .Case("v0", 2)
3822 .Case("v1", 3)
3823 .Case("s0", 16)
3824 .Case("s1", 17)
3825 .Case("s2", 18)
3826 .Case("s3", 19)
3827 .Case("s4", 20)
3828 .Case("s5", 21)
3829 .Case("s6", 22)
3830 .Case("s7", 23)
3831 .Case("k0", 26)
3832 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003833 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00003834 .Case("sp", 29)
3835 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003836 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00003837 .Case("ra", 31)
3838 .Case("t0", 8)
3839 .Case("t1", 9)
3840 .Case("t2", 10)
3841 .Case("t3", 11)
3842 .Case("t4", 12)
3843 .Case("t5", 13)
3844 .Case("t6", 14)
3845 .Case("t7", 15)
3846 .Case("t8", 24)
3847 .Case("t9", 25)
3848 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003849
Toma Tabacufda445c2014-09-15 15:33:01 +00003850 if (!(isABI_N32() || isABI_N64()))
3851 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003852
Daniel Sandersef638fe2014-10-03 15:37:37 +00003853 if (12 <= CC && CC <= 15) {
3854 // Name is one of t4-t7
3855 AsmToken RegTok = getLexer().peekTok();
3856 SMRange RegRange = RegTok.getLocRange();
3857
3858 StringRef FixedName = StringSwitch<StringRef>(Name)
3859 .Case("t4", "t0")
3860 .Case("t5", "t1")
3861 .Case("t6", "t2")
3862 .Case("t7", "t3")
3863 .Default("");
3864 assert(FixedName != "" && "Register name is not one of t4-t7.");
3865
3866 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
3867 "Did you mean $" + FixedName + "?", RegRange);
3868 }
3869
Toma Tabacufda445c2014-09-15 15:33:01 +00003870 // Although SGI documentation just cuts out t0-t3 for n32/n64,
3871 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
3872 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
3873 if (8 <= CC && CC <= 11)
3874 CC += 4;
3875
3876 if (CC == -1)
3877 CC = StringSwitch<unsigned>(Name)
3878 .Case("a4", 8)
3879 .Case("a5", 9)
3880 .Case("a6", 10)
3881 .Case("a7", 11)
3882 .Case("kt0", 26)
3883 .Case("kt1", 27)
3884 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003885
3886 return CC;
3887}
Jack Carterd0bd6422013-04-18 00:41:53 +00003888
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003889int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
3890 int CC;
3891
3892 CC = StringSwitch<unsigned>(Name)
3893 .Case("hwr_cpunum", 0)
3894 .Case("hwr_synci_step", 1)
3895 .Case("hwr_cc", 2)
3896 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00003897 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003898 .Default(-1);
3899
3900 return CC;
3901}
3902
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003903int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003904
Jack Cartera63b16a2012-09-07 00:23:42 +00003905 if (Name[0] == 'f') {
3906 StringRef NumString = Name.substr(1);
3907 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003908 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003909 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003910 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00003911 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003912 return IntVal;
3913 }
3914 return -1;
3915}
Jack Cartera63b16a2012-09-07 00:23:42 +00003916
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003917int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
3918
3919 if (Name.startswith("fcc")) {
3920 StringRef NumString = Name.substr(3);
3921 unsigned IntVal;
3922 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003923 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003924 if (IntVal > 7) // There are only 8 fcc registers.
3925 return -1;
3926 return IntVal;
3927 }
3928 return -1;
3929}
3930
3931int MipsAsmParser::matchACRegisterName(StringRef Name) {
3932
Akira Hatanaka274d24c2013-08-14 01:15:52 +00003933 if (Name.startswith("ac")) {
3934 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003935 unsigned IntVal;
3936 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003937 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003938 if (IntVal > 3) // There are only 3 acc registers.
3939 return -1;
3940 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00003941 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003942 return -1;
3943}
Jack Carterd0bd6422013-04-18 00:41:53 +00003944
Jack Carter5dc8ac92013-09-25 23:50:44 +00003945int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
3946 unsigned IntVal;
3947
3948 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
3949 return -1;
3950
3951 if (IntVal > 31)
3952 return -1;
3953
3954 return IntVal;
3955}
3956
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003957int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
3958 int CC;
3959
3960 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00003961 .Case("msair", 0)
3962 .Case("msacsr", 1)
3963 .Case("msaaccess", 2)
3964 .Case("msasave", 3)
3965 .Case("msamodify", 4)
3966 .Case("msarequest", 5)
3967 .Case("msamap", 6)
3968 .Case("msaunmap", 7)
3969 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003970
3971 return CC;
3972}
3973
Toma Tabacu89a712b2015-04-15 10:48:56 +00003974unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00003975 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00003976 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00003977 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00003978 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00003979 return 0;
3980 }
3981 unsigned AT = getReg(
3982 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00003983 return AT;
3984}
Jack Carter0b744b32012-10-04 02:29:46 +00003985
Jack Carterd0bd6422013-04-18 00:41:53 +00003986unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00003987 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00003988}
3989
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003990unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003991 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00003992 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003993}
3994
Jack Carter873c7242013-01-12 01:03:14 +00003995int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003996 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00003997 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00003998 return -1;
3999
Jack Carter873c7242013-01-12 01:03:14 +00004000 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00004001}
4002
Toma Tabacu13964452014-09-04 13:23:44 +00004003bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004004 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004005 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004006
Jack Carter30a59822012-10-04 04:03:53 +00004007 // Check if the current operand has a custom associated parser, if so, try to
4008 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00004009 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4010 if (ResTy == MatchOperand_Success)
4011 return false;
4012 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4013 // there was a match, but an error occurred, in which case, just return that
4014 // the operand parsing failed.
4015 if (ResTy == MatchOperand_ParseFail)
4016 return true;
4017
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004018 DEBUG(dbgs() << ".. Generic Parser\n");
4019
Jack Carterb4dbc172012-09-05 23:34:03 +00004020 switch (getLexer().getKind()) {
4021 default:
4022 Error(Parser.getTok().getLoc(), "unexpected token in operand");
4023 return true;
4024 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00004025 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00004026 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00004027
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004028 // Almost all registers have been parsed by custom parsers. There is only
4029 // one exception to this. $zero (and it's alias $0) will reach this point
4030 // for div, divu, and similar instructions because it is not an operand
4031 // to the instruction definition but an explicit register. Special case
4032 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00004033 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00004034 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004035
Jack Carterd0bd6422013-04-18 00:41:53 +00004036 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00004037 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004038 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00004039 return true;
4040
Jack Carter873c7242013-01-12 01:03:14 +00004041 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00004042 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00004043 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00004044 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004045 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00004046
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004047 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004048 return false;
4049 }
Vladimir Medic4c299852013-11-06 11:27:05 +00004050 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00004051 case AsmToken::LParen:
4052 case AsmToken::Minus:
4053 case AsmToken::Plus:
4054 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00004055 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00004056 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004057 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00004058 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004059 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00004060 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00004061 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00004062 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004063 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00004064 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00004065 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00004066 return true;
4067
Jack Carter873c7242013-01-12 01:03:14 +00004068 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4069
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004070 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00004071 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004072 } // case AsmToken::Percent
4073 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00004074 return true;
4075}
4076
Vladimir Medic4c299852013-11-06 11:27:05 +00004077const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00004078 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00004079 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00004080 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00004081 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00004082 // It's a constant, evaluate reloc value.
4083 int16_t Val;
4084 switch (getVariantKind(RelocStr)) {
4085 case MCSymbolRefExpr::VK_Mips_ABS_LO:
4086 // Get the 1st 16-bits.
4087 Val = MCE->getValue() & 0xffff;
4088 break;
4089 case MCSymbolRefExpr::VK_Mips_ABS_HI:
Simon Atanasyan2fc1e3b2016-02-09 22:31:49 +00004090 case MCSymbolRefExpr::VK_Mips_GOT:
Sasa Stankovic06c47802014-04-03 10:37:45 +00004091 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
4092 // 16 bits being negative.
4093 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
4094 break;
4095 case MCSymbolRefExpr::VK_Mips_HIGHER:
4096 // Get the 3rd 16-bits.
4097 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
4098 break;
4099 case MCSymbolRefExpr::VK_Mips_HIGHEST:
4100 // Get the 4th 16-bits.
4101 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
4102 break;
4103 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00004104 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00004105 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00004106 return MCConstantExpr::create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00004107 }
4108
Jack Carterb5cf5902013-04-17 00:18:04 +00004109 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004110 // It's a symbol, create a symbolic expression from the symbol.
Toma Tabacu07c97b32015-06-17 10:43:45 +00004111 const MCSymbol *Symbol = &MSRE->getSymbol();
Jack Carterb5cf5902013-04-17 00:18:04 +00004112 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004113 Res = MCSymbolRefExpr::create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004114 return Res;
4115 }
4116
4117 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00004118 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
4119
Sasa Stankovic06c47802014-04-03 10:37:45 +00004120 // Try to create target expression.
4121 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
Jim Grosbach13760bd2015-05-30 01:25:56 +00004122 return MipsMCExpr::create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00004123
Jack Carterd0bd6422013-04-18 00:41:53 +00004124 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
4125 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004126 Res = MCBinaryExpr::create(BE->getOpcode(), LExp, RExp, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004127 return Res;
4128 }
4129
4130 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004131 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004132 Res = MCUnaryExpr::create(UN->getOpcode(), UnExp, getContext());
Jack Carterd0bd6422013-04-18 00:41:53 +00004133 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00004134 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004135 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00004136 return Expr;
4137}
4138
4139bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
4140
4141 switch (Expr->getKind()) {
4142 case MCExpr::Constant:
4143 return true;
4144 case MCExpr::SymbolRef:
4145 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
4146 case MCExpr::Binary:
4147 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
4148 if (!isEvaluated(BE->getLHS()))
4149 return false;
4150 return isEvaluated(BE->getRHS());
4151 }
4152 case MCExpr::Unary:
4153 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00004154 case MCExpr::Target:
4155 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004156 }
Jack Carterb5cf5902013-04-17 00:18:04 +00004157 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00004158}
Jack Carterd0bd6422013-04-18 00:41:53 +00004159
Jack Carterb5cf5902013-04-17 00:18:04 +00004160bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004161 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00004162 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00004163 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00004164 if (Tok.isNot(AsmToken::Identifier))
4165 return true;
4166
Yaron Keren075759a2015-03-30 15:42:36 +00004167 std::string Str = Tok.getIdentifier();
Jack Carterb5cf5902013-04-17 00:18:04 +00004168
Jack Carterd0bd6422013-04-18 00:41:53 +00004169 Parser.Lex(); // Eat the identifier.
4170 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004171 const MCExpr *IdVal;
4172 SMLoc EndLoc;
4173
4174 if (getLexer().getKind() == AsmToken::LParen) {
4175 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004176 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004177 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004178 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004179 const AsmToken &nextTok = Parser.getTok();
4180 if (nextTok.isNot(AsmToken::Identifier))
4181 return true;
4182 Str += "(%";
4183 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00004184 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00004185 if (getLexer().getKind() != AsmToken::LParen)
4186 return true;
4187 } else
4188 break;
4189 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004190 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00004191 return true;
4192
4193 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00004194 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004195
4196 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00004197 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004198
Jack Carterd0bd6422013-04-18 00:41:53 +00004199 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00004200 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004201}
4202
Jack Carterb4dbc172012-09-05 23:34:03 +00004203bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
4204 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004205 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00004206 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004207 if (ResTy == MatchOperand_Success) {
4208 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00004209 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004210 StartLoc = Operand.getStartLoc();
4211 EndLoc = Operand.getEndLoc();
4212
4213 // AFAIK, we only support numeric registers and named GPR's in CFI
4214 // directives.
4215 // Don't worry about eating tokens before failing. Using an unrecognised
4216 // register is a parse error.
4217 if (Operand.isGPRAsmReg()) {
4218 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004219 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004220 }
4221
4222 return (RegNo == (unsigned)-1);
4223 }
4224
4225 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00004226 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00004227}
4228
Jack Carterb5cf5902013-04-17 00:18:04 +00004229bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004230 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00004231 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00004232 bool Result = true;
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004233 unsigned NumOfLParen = 0;
Jack Carterb5cf5902013-04-17 00:18:04 +00004234
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004235 while (getLexer().getKind() == AsmToken::LParen) {
Jack Carterb5cf5902013-04-17 00:18:04 +00004236 Parser.Lex();
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004237 ++NumOfLParen;
4238 }
Jack Carter873c7242013-01-12 01:03:14 +00004239
Jack Carterd0bd6422013-04-18 00:41:53 +00004240 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00004241 default:
4242 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00004243 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00004244 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00004245 case AsmToken::Integer:
4246 case AsmToken::Minus:
4247 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00004248 if (isParenExpr)
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004249 Result = getParser().parseParenExprOfDepth(NumOfLParen, Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00004250 else
4251 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00004252 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00004253 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004254 break;
Jack Carter873c7242013-01-12 01:03:14 +00004255 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00004256 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00004257 }
Jack Carterb5cf5902013-04-17 00:18:04 +00004258 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004259}
4260
David Blaikie960ea3f2014-06-08 16:18:35 +00004261MipsAsmParser::OperandMatchResultTy
4262MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004263 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004264 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00004265 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00004266 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00004267 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004268 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00004269 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00004270 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00004271
Jack Carterb5cf5902013-04-17 00:18:04 +00004272 if (getLexer().getKind() == AsmToken::LParen) {
4273 Parser.Lex();
4274 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004275 }
4276
Jack Carterb5cf5902013-04-17 00:18:04 +00004277 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004278 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00004279 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004280
Jack Carterd0bd6422013-04-18 00:41:53 +00004281 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004282 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004283 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00004284 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00004285 SMLoc E =
4286 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004287 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00004288 return MatchOperand_Success;
4289 }
4290 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004291 SMLoc E =
4292 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00004293
Jack Carterd0bd6422013-04-18 00:41:53 +00004294 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004295 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00004296 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004297 S, E, *this);
4298 Operands.push_back(
4299 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00004300 return MatchOperand_Success;
4301 }
4302 Error(Parser.getTok().getLoc(), "'(' expected");
4303 return MatchOperand_ParseFail;
4304 }
4305
Jack Carterd0bd6422013-04-18 00:41:53 +00004306 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004307 }
4308
Toma Tabacu13964452014-09-04 13:23:44 +00004309 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004310 if (Res != MatchOperand_Success)
4311 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004312
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004313 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00004314 Error(Parser.getTok().getLoc(), "')' expected");
4315 return MatchOperand_ParseFail;
4316 }
4317
Jack Carter873c7242013-01-12 01:03:14 +00004318 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4319
Jack Carterd0bd6422013-04-18 00:41:53 +00004320 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004321
Craig Topper062a2ba2014-04-25 05:30:21 +00004322 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004323 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00004324
Jack Carterd0bd6422013-04-18 00:41:53 +00004325 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00004326 std::unique_ptr<MipsOperand> op(
4327 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00004328 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004329 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004330 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00004331 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004332 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
4333 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004334 if (IdVal->evaluateAsAbsolute(Imm))
4335 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004336 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004337 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00004338 getContext());
4339 }
4340
David Blaikie960ea3f2014-06-08 16:18:35 +00004341 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004342 return MatchOperand_Success;
4343}
4344
David Blaikie960ea3f2014-06-08 16:18:35 +00004345bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004346 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00004347 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00004348 if (Sym) {
4349 SMLoc S = Parser.getTok().getLoc();
4350 const MCExpr *Expr;
4351 if (Sym->isVariable())
4352 Expr = Sym->getVariableValue();
4353 else
4354 return false;
4355 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004356 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00004357 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00004358 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004359 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004360 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00004361 if (ResTy == MatchOperand_Success) {
4362 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00004363 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00004364 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004365 llvm_unreachable("Should never ParseFail");
4366 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00004367 }
4368 } else if (Expr->getKind() == MCExpr::Constant) {
4369 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00004370 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00004371 Operands.push_back(
4372 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00004373 return true;
4374 }
4375 }
4376 return false;
4377}
Jack Carterd0bd6422013-04-18 00:41:53 +00004378
Jack Carter873c7242013-01-12 01:03:14 +00004379MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004380MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00004381 StringRef Identifier,
4382 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004383 int Index = matchCPURegisterName(Identifier);
4384 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004385 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004386 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4387 return MatchOperand_Success;
4388 }
4389
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004390 Index = matchHWRegsRegisterName(Identifier);
4391 if (Index != -1) {
4392 Operands.push_back(MipsOperand::createHWRegsReg(
4393 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4394 return MatchOperand_Success;
4395 }
4396
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004397 Index = matchFPURegisterName(Identifier);
4398 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004399 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004400 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4401 return MatchOperand_Success;
4402 }
4403
4404 Index = matchFCCRegisterName(Identifier);
4405 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004406 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004407 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4408 return MatchOperand_Success;
4409 }
4410
4411 Index = matchACRegisterName(Identifier);
4412 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004413 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004414 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4415 return MatchOperand_Success;
4416 }
4417
4418 Index = matchMSA128RegisterName(Identifier);
4419 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004420 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004421 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4422 return MatchOperand_Success;
4423 }
4424
4425 Index = matchMSA128CtrlRegisterName(Identifier);
4426 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004427 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004428 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4429 return MatchOperand_Success;
4430 }
4431
4432 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00004433}
4434
4435MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004436MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004437 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00004438 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004439
4440 if (Token.is(AsmToken::Identifier)) {
4441 DEBUG(dbgs() << ".. identifier\n");
4442 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00004443 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004444 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00004445 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004446 } else if (Token.is(AsmToken::Integer)) {
4447 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00004448 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004449 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
4450 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004451 return MatchOperand_Success;
4452 }
4453
4454 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
4455
4456 return MatchOperand_NoMatch;
4457}
4458
David Blaikie960ea3f2014-06-08 16:18:35 +00004459MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004460MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004461 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004462 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004463
4464 auto Token = Parser.getTok();
4465
4466 SMLoc S = Token.getLoc();
4467
4468 if (Token.isNot(AsmToken::Dollar)) {
4469 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
4470 if (Token.is(AsmToken::Identifier)) {
4471 if (searchSymbolAlias(Operands))
4472 return MatchOperand_Success;
4473 }
4474 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
4475 return MatchOperand_NoMatch;
4476 }
4477 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004478
Toma Tabacu13964452014-09-04 13:23:44 +00004479 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00004480 if (ResTy == MatchOperand_Success) {
4481 Parser.Lex(); // $
4482 Parser.Lex(); // identifier
4483 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004484 return ResTy;
4485}
4486
4487MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004488MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004489 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004490 switch (getLexer().getKind()) {
4491 default:
4492 return MatchOperand_NoMatch;
4493 case AsmToken::LParen:
4494 case AsmToken::Minus:
4495 case AsmToken::Plus:
4496 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00004497 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004498 case AsmToken::String:
4499 break;
4500 }
4501
4502 const MCExpr *IdVal;
4503 SMLoc S = Parser.getTok().getLoc();
4504 if (getParser().parseExpression(IdVal))
4505 return MatchOperand_ParseFail;
4506
4507 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4508 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
4509 return MatchOperand_Success;
4510}
4511
David Blaikie960ea3f2014-06-08 16:18:35 +00004512MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004513MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004514 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004515 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004516
4517 SMLoc S = getLexer().getLoc();
4518
4519 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00004520 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004521 if (ResTy != MatchOperand_NoMatch)
4522 return ResTy;
4523
Daniel Sanders315386c2014-04-01 10:40:14 +00004524 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00004525 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00004526 if (ResTy != MatchOperand_NoMatch)
4527 return ResTy;
4528
Daniel Sandersffd84362014-04-01 10:41:48 +00004529 const MCExpr *Expr = nullptr;
4530 if (Parser.parseExpression(Expr)) {
4531 // We have no way of knowing if a symbol was consumed so we must ParseFail
4532 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004533 }
Daniel Sandersffd84362014-04-01 10:41:48 +00004534 Operands.push_back(
4535 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004536 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00004537}
4538
Vladimir Medic2b953d02013-10-01 09:48:56 +00004539MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00004540MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004541 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00004542 const MCExpr *IdVal;
4543 // If the first token is '$' we may have register operand.
4544 if (Parser.getTok().is(AsmToken::Dollar))
4545 return MatchOperand_NoMatch;
4546 SMLoc S = Parser.getTok().getLoc();
4547 if (getParser().parseExpression(IdVal))
4548 return MatchOperand_ParseFail;
4549 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00004550 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00004551 int64_t Val = MCE->getValue();
4552 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4553 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00004554 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00004555 return MatchOperand_Success;
4556}
4557
Matheus Almeida779c5932013-11-18 12:32:49 +00004558MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004559MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004560 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00004561 switch (getLexer().getKind()) {
4562 default:
4563 return MatchOperand_NoMatch;
4564 case AsmToken::LParen:
4565 case AsmToken::Plus:
4566 case AsmToken::Minus:
4567 case AsmToken::Integer:
4568 break;
4569 }
4570
4571 const MCExpr *Expr;
4572 SMLoc S = Parser.getTok().getLoc();
4573
4574 if (getParser().parseExpression(Expr))
4575 return MatchOperand_ParseFail;
4576
4577 int64_t Val;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004578 if (!Expr->evaluateAsAbsolute(Val)) {
Matheus Almeida779c5932013-11-18 12:32:49 +00004579 Error(S, "expected immediate value");
4580 return MatchOperand_ParseFail;
4581 }
4582
4583 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
4584 // and because the CPU always adds one to the immediate field, the allowed
4585 // range becomes 1..4. We'll only check the range here and will deal
4586 // with the addition/subtraction when actually decoding/encoding
4587 // the instruction.
4588 if (Val < 1 || Val > 4) {
4589 Error(S, "immediate not in range (1..4)");
4590 return MatchOperand_ParseFail;
4591 }
4592
Jack Carter3b2c96e2014-01-22 23:31:38 +00004593 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004594 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00004595 return MatchOperand_Success;
4596}
4597
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004598MipsAsmParser::OperandMatchResultTy
4599MipsAsmParser::parseRegisterList(OperandVector &Operands) {
4600 MCAsmParser &Parser = getParser();
4601 SmallVector<unsigned, 10> Regs;
4602 unsigned RegNo;
4603 unsigned PrevReg = Mips::NoRegister;
4604 bool RegRange = false;
4605 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4606
4607 if (Parser.getTok().isNot(AsmToken::Dollar))
4608 return MatchOperand_ParseFail;
4609
4610 SMLoc S = Parser.getTok().getLoc();
4611 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
4612 SMLoc E = getLexer().getLoc();
4613 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
4614 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
4615 if (RegRange) {
4616 // Remove last register operand because registers from register range
4617 // should be inserted first.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004618 if ((isGP64bit() && RegNo == Mips::RA_64) ||
4619 (!isGP64bit() && RegNo == Mips::RA)) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004620 Regs.push_back(RegNo);
4621 } else {
4622 unsigned TmpReg = PrevReg + 1;
4623 while (TmpReg <= RegNo) {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004624 if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) ||
4625 (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) &&
4626 isGP64bit())) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004627 Error(E, "invalid register operand");
4628 return MatchOperand_ParseFail;
4629 }
4630
4631 PrevReg = TmpReg;
4632 Regs.push_back(TmpReg++);
4633 }
4634 }
4635
4636 RegRange = false;
4637 } else {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004638 if ((PrevReg == Mips::NoRegister) &&
4639 ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) ||
4640 (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA)))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004641 Error(E, "$16 or $31 expected");
4642 return MatchOperand_ParseFail;
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004643 } else if (!(((RegNo == Mips::FP || RegNo == Mips::RA ||
4644 (RegNo >= Mips::S0 && RegNo <= Mips::S7)) &&
4645 !isGP64bit()) ||
4646 ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 ||
4647 (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) &&
4648 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004649 Error(E, "invalid register operand");
4650 return MatchOperand_ParseFail;
4651 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004652 ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) ||
4653 (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 &&
4654 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004655 Error(E, "consecutive register numbers expected");
4656 return MatchOperand_ParseFail;
4657 }
4658
4659 Regs.push_back(RegNo);
4660 }
4661
4662 if (Parser.getTok().is(AsmToken::Minus))
4663 RegRange = true;
4664
4665 if (!Parser.getTok().isNot(AsmToken::Minus) &&
4666 !Parser.getTok().isNot(AsmToken::Comma)) {
4667 Error(E, "',' or '-' expected");
4668 return MatchOperand_ParseFail;
4669 }
4670
4671 Lex(); // Consume comma or minus
4672 if (Parser.getTok().isNot(AsmToken::Dollar))
4673 break;
4674
4675 PrevReg = RegNo;
4676 }
4677
4678 SMLoc E = Parser.getTok().getLoc();
4679 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4680 parseMemOperand(Operands);
4681 return MatchOperand_Success;
4682}
4683
Zoran Jovanovic2deca342014-12-16 14:59:10 +00004684MipsAsmParser::OperandMatchResultTy
4685MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
4686 MCAsmParser &Parser = getParser();
4687
4688 SMLoc S = Parser.getTok().getLoc();
4689 if (parseAnyRegister(Operands) != MatchOperand_Success)
4690 return MatchOperand_ParseFail;
4691
4692 SMLoc E = Parser.getTok().getLoc();
4693 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
4694 unsigned Reg = Op.getGPR32Reg();
4695 Operands.pop_back();
4696 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
4697 return MatchOperand_Success;
4698}
4699
Zoran Jovanovic41688672015-02-10 16:36:20 +00004700MipsAsmParser::OperandMatchResultTy
4701MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
4702 MCAsmParser &Parser = getParser();
4703 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4704 SmallVector<unsigned, 10> Regs;
4705
4706 if (Parser.getTok().isNot(AsmToken::Dollar))
4707 return MatchOperand_ParseFail;
4708
4709 SMLoc S = Parser.getTok().getLoc();
4710
4711 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4712 return MatchOperand_ParseFail;
4713
4714 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4715 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4716 Regs.push_back(RegNo);
4717
4718 SMLoc E = Parser.getTok().getLoc();
4719 if (Parser.getTok().isNot(AsmToken::Comma)) {
4720 Error(E, "',' expected");
4721 return MatchOperand_ParseFail;
4722 }
4723
4724 // Remove comma.
4725 Parser.Lex();
4726
4727 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4728 return MatchOperand_ParseFail;
4729
4730 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4731 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4732 Regs.push_back(RegNo);
4733
4734 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4735
4736 return MatchOperand_Success;
4737}
4738
Jack Carterdc1e35d2012-09-06 20:00:02 +00004739MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
4740
Vladimir Medic4c299852013-11-06 11:27:05 +00004741 MCSymbolRefExpr::VariantKind VK =
4742 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
4743 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
4744 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
4745 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
4746 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
4747 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
4748 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
4749 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
4750 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
4751 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
4752 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
4753 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
4754 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
4755 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
4756 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
4757 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
4758 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
4759 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00004760 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
4761 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
4762 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
4763 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
4764 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
4765 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00004766 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
4767 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00004768 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00004769
Matheus Almeida2852af82014-04-22 10:15:54 +00004770 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00004771
Jack Carterdc1e35d2012-09-06 20:00:02 +00004772 return VK;
4773}
Jack Cartera63b16a2012-09-07 00:23:42 +00004774
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004775/// Sometimes (i.e. load/stores) the operand may be followed immediately by
4776/// either this.
4777/// ::= '(', register, ')'
4778/// handle it before we iterate so we don't get tripped up by the lack of
4779/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004780bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004781 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004782 if (getLexer().is(AsmToken::LParen)) {
4783 Operands.push_back(
4784 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
4785 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004786 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004787 SMLoc Loc = getLexer().getLoc();
4788 Parser.eatToEndOfStatement();
4789 return Error(Loc, "unexpected token in argument list");
4790 }
4791 if (Parser.getTok().isNot(AsmToken::RParen)) {
4792 SMLoc Loc = getLexer().getLoc();
4793 Parser.eatToEndOfStatement();
4794 return Error(Loc, "unexpected token, expected ')'");
4795 }
4796 Operands.push_back(
4797 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
4798 Parser.Lex();
4799 }
4800 return false;
4801}
4802
4803/// Sometimes (i.e. in MSA) the operand may be followed immediately by
4804/// either one of these.
4805/// ::= '[', register, ']'
4806/// ::= '[', integer, ']'
4807/// handle it before we iterate so we don't get tripped up by the lack of
4808/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004809bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00004810 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004811 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004812 if (getLexer().is(AsmToken::LBrac)) {
4813 Operands.push_back(
4814 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
4815 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004816 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004817 SMLoc Loc = getLexer().getLoc();
4818 Parser.eatToEndOfStatement();
4819 return Error(Loc, "unexpected token in argument list");
4820 }
4821 if (Parser.getTok().isNot(AsmToken::RBrac)) {
4822 SMLoc Loc = getLexer().getLoc();
4823 Parser.eatToEndOfStatement();
4824 return Error(Loc, "unexpected token, expected ']'");
4825 }
4826 Operands.push_back(
4827 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
4828 Parser.Lex();
4829 }
4830 return false;
4831}
4832
David Blaikie960ea3f2014-06-08 16:18:35 +00004833bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
4834 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004835 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004836 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004837
4838 // We have reached first instruction, module directive are now forbidden.
4839 getTargetStreamer().forbidModuleDirective();
4840
Vladimir Medic74593e62013-07-17 15:00:42 +00004841 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00004842 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00004843 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00004844 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00004845 }
Vladimir Medic64828a12013-07-16 10:07:14 +00004846 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004847 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004848
4849 // Read the remaining operands.
4850 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4851 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004852 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004853 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004854 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004855 return Error(Loc, "unexpected token in argument list");
4856 }
Toma Tabacu13964452014-09-04 13:23:44 +00004857 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004858 return true;
4859 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00004860
Jack Carterd0bd6422013-04-18 00:41:53 +00004861 while (getLexer().is(AsmToken::Comma)) {
4862 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00004863 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004864 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004865 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004866 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004867 return Error(Loc, "unexpected token in argument list");
4868 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004869 // Parse bracket and parenthesis suffixes before we iterate
4870 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00004871 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004872 return true;
4873 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00004874 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004875 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00004876 }
4877 }
Jack Carterb4dbc172012-09-05 23:34:03 +00004878 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4879 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004880 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004881 return Error(Loc, "unexpected token in argument list");
4882 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004883 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00004884 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00004885}
4886
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004887bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004888 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004889 SMLoc Loc = getLexer().getLoc();
4890 Parser.eatToEndOfStatement();
4891 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00004892}
4893
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004894bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004895 return Error(Loc, ErrorMsg);
4896}
4897
Jack Carter0b744b32012-10-04 02:29:46 +00004898bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004899 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004900 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00004901
4902 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00004903 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00004904
4905 Parser.Lex(); // Eat "noat".
4906
Jack Carterd0bd6422013-04-18 00:41:53 +00004907 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004908 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004909 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004910 return false;
4911 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004912
4913 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004914 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004915 return false;
4916}
Jack Carterd0bd6422013-04-18 00:41:53 +00004917
Jack Carter0b744b32012-10-04 02:29:46 +00004918bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00004919 // Line can be: ".set at", which sets $at to $1
4920 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00004921 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00004922 Parser.Lex(); // Eat "at".
4923
Jack Carter0b744b32012-10-04 02:29:46 +00004924 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004925 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00004926 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00004927
4928 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004929 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004930 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00004931 }
4932
4933 if (getLexer().isNot(AsmToken::Equal)) {
4934 reportParseError("unexpected token, expected equals sign");
4935 return false;
4936 }
4937 Parser.Lex(); // Eat "=".
4938
4939 if (getLexer().isNot(AsmToken::Dollar)) {
4940 if (getLexer().is(AsmToken::EndOfStatement)) {
4941 reportParseError("no register specified");
4942 return false;
4943 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00004944 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00004945 return false;
4946 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004947 }
4948 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00004949
Toma Tabacu16a74492015-02-13 10:30:57 +00004950 // Find out what "reg" is.
4951 unsigned AtRegNo;
4952 const AsmToken &Reg = Parser.getTok();
4953 if (Reg.is(AsmToken::Identifier)) {
4954 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
4955 } else if (Reg.is(AsmToken::Integer)) {
4956 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00004957 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00004958 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00004959 return false;
4960 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004961
4962 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00004963 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004964 reportParseError("invalid register");
4965 return false;
4966 }
4967 Parser.Lex(); // Eat "reg".
4968
4969 // If this is not the end of the statement, report an error.
4970 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4971 reportParseError("unexpected token, expected end of statement");
4972 return false;
4973 }
4974
4975 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
4976
4977 Parser.Lex(); // Consume the EndOfStatement.
4978 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004979}
4980
4981bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004982 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004983 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004984 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004985 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004986 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004987 return false;
4988 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004989 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00004990 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004991 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004992 return false;
4993}
4994
4995bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004996 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004997 Parser.Lex();
4998 // If this is not the end of the statement, report an error.
4999 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005000 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005001 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00005002 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005003 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00005004 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00005005 Parser.Lex(); // Consume the EndOfStatement.
5006 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005007}
5008
5009bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005010 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00005011 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00005012 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005013 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005014 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005015 return false;
5016 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005017 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00005018 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00005019 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005020 return false;
5021}
5022
5023bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005024 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00005025 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00005026 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005027 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005028 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005029 return false;
5030 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005031 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00005032 reportParseError("`noreorder' must be set before `nomacro'");
5033 return false;
5034 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005035 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00005036 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00005037 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005038 return false;
5039}
Jack Carterd76b2372013-03-21 21:44:16 +00005040
Daniel Sanders44934432014-08-07 12:03:36 +00005041bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005042 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00005043 Parser.Lex();
5044
5045 // If this is not the end of the statement, report an error.
5046 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005047 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00005048
5049 setFeatureBits(Mips::FeatureMSA, "msa");
5050 getTargetStreamer().emitDirectiveSetMsa();
5051 return false;
5052}
5053
5054bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005055 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00005056 Parser.Lex();
5057
5058 // If this is not the end of the statement, report an error.
5059 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005060 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00005061
5062 clearFeatureBits(Mips::FeatureMSA, "msa");
5063 getTargetStreamer().emitDirectiveSetNoMsa();
5064 return false;
5065}
5066
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005067bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005068 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005069 Parser.Lex(); // Eat "nodsp".
5070
5071 // If this is not the end of the statement, report an error.
5072 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5073 reportParseError("unexpected token, expected end of statement");
5074 return false;
5075 }
5076
5077 clearFeatureBits(Mips::FeatureDSP, "dsp");
5078 getTargetStreamer().emitDirectiveSetNoDsp();
5079 return false;
5080}
5081
Toma Tabacucc2502d2014-11-04 17:18:07 +00005082bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005083 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005084 Parser.Lex(); // Eat "mips16".
5085
Jack Carter39536722014-01-22 23:08:42 +00005086 // If this is not the end of the statement, report an error.
5087 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005088 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00005089 return false;
5090 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00005091
5092 setFeatureBits(Mips::FeatureMips16, "mips16");
5093 getTargetStreamer().emitDirectiveSetMips16();
5094 Parser.Lex(); // Consume the EndOfStatement.
5095 return false;
5096}
5097
5098bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005099 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005100 Parser.Lex(); // Eat "nomips16".
5101
5102 // If this is not the end of the statement, report an error.
5103 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5104 reportParseError("unexpected token, expected end of statement");
5105 return false;
5106 }
5107
5108 clearFeatureBits(Mips::FeatureMips16, "mips16");
5109 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00005110 Parser.Lex(); // Consume the EndOfStatement.
5111 return false;
5112}
5113
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005114bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005115 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005116 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005117 // Line can be: .set fp=32
5118 // .set fp=xx
5119 // .set fp=64
5120 Parser.Lex(); // Eat fp token
5121 AsmToken Tok = Parser.getTok();
5122 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005123 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005124 return false;
5125 }
5126 Parser.Lex(); // Eat '=' token.
5127 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005128
5129 if (!parseFpABIValue(FpAbiVal, ".set"))
5130 return false;
5131
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005132 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005133 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005134 return false;
5135 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005136 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005137 Parser.Lex(); // Consume the EndOfStatement.
5138 return false;
5139}
5140
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005141bool MipsAsmParser::parseSetOddSPRegDirective() {
5142 MCAsmParser &Parser = getParser();
5143
5144 Parser.Lex(); // Eat "oddspreg".
5145 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5146 reportParseError("unexpected token, expected end of statement");
5147 return false;
5148 }
5149
5150 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5151 getTargetStreamer().emitDirectiveSetOddSPReg();
5152 return false;
5153}
5154
5155bool MipsAsmParser::parseSetNoOddSPRegDirective() {
5156 MCAsmParser &Parser = getParser();
5157
5158 Parser.Lex(); // Eat "nooddspreg".
5159 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5160 reportParseError("unexpected token, expected end of statement");
5161 return false;
5162 }
5163
5164 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5165 getTargetStreamer().emitDirectiveSetNoOddSPReg();
5166 return false;
5167}
5168
Toma Tabacu9db22db2014-09-09 10:15:38 +00005169bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005170 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005171 SMLoc Loc = getLexer().getLoc();
5172
5173 Parser.Lex();
5174 if (getLexer().isNot(AsmToken::EndOfStatement))
5175 return reportParseError("unexpected token, expected end of statement");
5176
5177 // Always keep an element on the options "stack" to prevent the user
5178 // from changing the initial options. This is how we remember them.
5179 if (AssemblerOptions.size() == 2)
5180 return reportParseError(Loc, ".set pop with no .set push");
5181
Akira Hatanakab11ef082015-11-14 06:35:56 +00005182 MCSubtargetInfo &STI = copySTI();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005183 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005184 setAvailableFeatures(
5185 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
5186 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00005187
5188 getTargetStreamer().emitDirectiveSetPop();
5189 return false;
5190}
5191
5192bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005193 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005194 Parser.Lex();
5195 if (getLexer().isNot(AsmToken::EndOfStatement))
5196 return reportParseError("unexpected token, expected end of statement");
5197
5198 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00005199 AssemblerOptions.push_back(
5200 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00005201
5202 getTargetStreamer().emitDirectiveSetPush();
5203 return false;
5204}
5205
Toma Tabacu29696502015-06-02 09:48:04 +00005206bool MipsAsmParser::parseSetSoftFloatDirective() {
5207 MCAsmParser &Parser = getParser();
5208 Parser.Lex();
5209 if (getLexer().isNot(AsmToken::EndOfStatement))
5210 return reportParseError("unexpected token, expected end of statement");
5211
5212 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5213 getTargetStreamer().emitDirectiveSetSoftFloat();
5214 return false;
5215}
5216
5217bool MipsAsmParser::parseSetHardFloatDirective() {
5218 MCAsmParser &Parser = getParser();
5219 Parser.Lex();
5220 if (getLexer().isNot(AsmToken::EndOfStatement))
5221 return reportParseError("unexpected token, expected end of statement");
5222
5223 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5224 getTargetStreamer().emitDirectiveSetHardFloat();
5225 return false;
5226}
5227
Jack Carterd76b2372013-03-21 21:44:16 +00005228bool MipsAsmParser::parseSetAssignment() {
5229 StringRef Name;
5230 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00005231 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00005232
5233 if (Parser.parseIdentifier(Name))
5234 reportParseError("expected identifier after .set");
5235
5236 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005237 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00005238 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00005239
Jack Carter3b2c96e2014-01-22 23:31:38 +00005240 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00005241 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00005242
Jim Grosbach6f482002015-05-18 18:43:14 +00005243 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00005244 Sym->setVariableValue(Value);
5245
5246 return false;
5247}
Jack Carterd0bd6422013-04-18 00:41:53 +00005248
Toma Tabacu26647792014-09-09 12:52:14 +00005249bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005250 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00005251 Parser.Lex();
5252 if (getLexer().isNot(AsmToken::EndOfStatement))
5253 return reportParseError("unexpected token, expected end of statement");
5254
5255 // Reset assembler options to their initial values.
Akira Hatanakab11ef082015-11-14 06:35:56 +00005256 MCSubtargetInfo &STI = copySTI();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005257 setAvailableFeatures(
5258 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
5259 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00005260 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
5261
5262 getTargetStreamer().emitDirectiveSetMips0();
5263 return false;
5264}
5265
Toma Tabacu85618b32014-08-19 14:22:52 +00005266bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005267 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00005268 Parser.Lex();
5269 if (getLexer().isNot(AsmToken::Equal))
5270 return reportParseError("unexpected token, expected equals sign");
5271
5272 Parser.Lex();
5273 StringRef Arch;
5274 if (Parser.parseIdentifier(Arch))
5275 return reportParseError("expected arch identifier");
5276
5277 StringRef ArchFeatureName =
5278 StringSwitch<StringRef>(Arch)
5279 .Case("mips1", "mips1")
5280 .Case("mips2", "mips2")
5281 .Case("mips3", "mips3")
5282 .Case("mips4", "mips4")
5283 .Case("mips5", "mips5")
5284 .Case("mips32", "mips32")
5285 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005286 .Case("mips32r3", "mips32r3")
5287 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005288 .Case("mips32r6", "mips32r6")
5289 .Case("mips64", "mips64")
5290 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005291 .Case("mips64r3", "mips64r3")
5292 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005293 .Case("mips64r6", "mips64r6")
5294 .Case("cnmips", "cnmips")
5295 .Case("r4000", "mips3") // This is an implementation of Mips3.
5296 .Default("");
5297
5298 if (ArchFeatureName.empty())
5299 return reportParseError("unsupported architecture");
5300
5301 selectArch(ArchFeatureName);
5302 getTargetStreamer().emitDirectiveSetArch(Arch);
5303 return false;
5304}
5305
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005306bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005307 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005308 Parser.Lex();
5309 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005310 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005311
Matheus Almeida2852af82014-04-22 10:15:54 +00005312 switch (Feature) {
5313 default:
5314 llvm_unreachable("Unimplemented feature");
5315 case Mips::FeatureDSP:
5316 setFeatureBits(Mips::FeatureDSP, "dsp");
5317 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005318 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005319 case Mips::FeatureMicroMips:
5320 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005321 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005322 case Mips::FeatureMips1:
5323 selectArch("mips1");
5324 getTargetStreamer().emitDirectiveSetMips1();
5325 break;
5326 case Mips::FeatureMips2:
5327 selectArch("mips2");
5328 getTargetStreamer().emitDirectiveSetMips2();
5329 break;
5330 case Mips::FeatureMips3:
5331 selectArch("mips3");
5332 getTargetStreamer().emitDirectiveSetMips3();
5333 break;
5334 case Mips::FeatureMips4:
5335 selectArch("mips4");
5336 getTargetStreamer().emitDirectiveSetMips4();
5337 break;
5338 case Mips::FeatureMips5:
5339 selectArch("mips5");
5340 getTargetStreamer().emitDirectiveSetMips5();
5341 break;
5342 case Mips::FeatureMips32:
5343 selectArch("mips32");
5344 getTargetStreamer().emitDirectiveSetMips32();
5345 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005346 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005347 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005348 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005349 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005350 case Mips::FeatureMips32r3:
5351 selectArch("mips32r3");
5352 getTargetStreamer().emitDirectiveSetMips32R3();
5353 break;
5354 case Mips::FeatureMips32r5:
5355 selectArch("mips32r5");
5356 getTargetStreamer().emitDirectiveSetMips32R5();
5357 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005358 case Mips::FeatureMips32r6:
5359 selectArch("mips32r6");
5360 getTargetStreamer().emitDirectiveSetMips32R6();
5361 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005362 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005363 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00005364 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005365 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005366 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005367 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005368 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005369 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005370 case Mips::FeatureMips64r3:
5371 selectArch("mips64r3");
5372 getTargetStreamer().emitDirectiveSetMips64R3();
5373 break;
5374 case Mips::FeatureMips64r5:
5375 selectArch("mips64r5");
5376 getTargetStreamer().emitDirectiveSetMips64R5();
5377 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005378 case Mips::FeatureMips64r6:
5379 selectArch("mips64r6");
5380 getTargetStreamer().emitDirectiveSetMips64R6();
5381 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005382 }
5383 return false;
5384}
5385
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005386bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005387 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005388 if (getLexer().isNot(AsmToken::Comma)) {
5389 SMLoc Loc = getLexer().getLoc();
5390 Parser.eatToEndOfStatement();
5391 return Error(Loc, ErrorStr);
5392 }
5393
Matheus Almeida2852af82014-04-22 10:15:54 +00005394 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005395 return true;
5396}
5397
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005398// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
5399// In this class, it is only used for .cprestore.
5400// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
5401// MipsTargetELFStreamer and MipsAsmParser.
5402bool MipsAsmParser::isPicAndNotNxxAbi() {
5403 return inPicMode() && !(isABI_N32() || isABI_N64());
5404}
5405
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005406bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00005407 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00005408 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005409
Toma Tabacudde4c462014-11-06 10:02:45 +00005410 if (inMips16Mode()) {
5411 reportParseError(".cpload is not supported in Mips16 mode");
5412 return false;
5413 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005414
David Blaikie960ea3f2014-06-08 16:18:35 +00005415 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00005416 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005417 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5418 reportParseError("expected register containing function address");
5419 return false;
5420 }
5421
David Blaikie960ea3f2014-06-08 16:18:35 +00005422 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
5423 if (!RegOpnd.isGPRAsmReg()) {
5424 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005425 return false;
5426 }
5427
Toma Tabacudde4c462014-11-06 10:02:45 +00005428 // If this is not the end of the statement, report an error.
5429 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5430 reportParseError("unexpected token, expected end of statement");
5431 return false;
5432 }
5433
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005434 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005435 return false;
5436}
5437
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005438bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
5439 MCAsmParser &Parser = getParser();
5440
5441 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
5442 // is used in non-PIC mode.
5443
5444 if (inMips16Mode()) {
5445 reportParseError(".cprestore is not supported in Mips16 mode");
5446 return false;
5447 }
5448
5449 // Get the stack offset value.
5450 const MCExpr *StackOffset;
5451 int64_t StackOffsetVal;
5452 if (Parser.parseExpression(StackOffset)) {
5453 reportParseError("expected stack offset value");
5454 return false;
5455 }
5456
5457 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
5458 reportParseError("stack offset is not an absolute expression");
5459 return false;
5460 }
5461
5462 if (StackOffsetVal < 0) {
5463 Warning(Loc, ".cprestore with negative stack offset has no effect");
5464 IsCpRestoreSet = false;
5465 } else {
5466 IsCpRestoreSet = true;
5467 CpRestoreOffset = StackOffsetVal;
5468 }
5469
5470 // If this is not the end of the statement, report an error.
5471 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5472 reportParseError("unexpected token, expected end of statement");
5473 return false;
5474 }
5475
5476 // Store the $gp on the stack.
5477 SmallVector<MCInst, 3> StoreInsts;
5478 createCpRestoreMemOp(false /*IsLoad*/, CpRestoreOffset /*StackOffset*/, Loc,
5479 StoreInsts);
5480
5481 getTargetStreamer().emitDirectiveCpRestore(StoreInsts, CpRestoreOffset);
5482 Parser.Lex(); // Consume the EndOfStatement.
5483 return false;
5484}
5485
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005486bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005487 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005488 unsigned FuncReg;
5489 unsigned Save;
5490 bool SaveIsReg = true;
5491
Matheus Almeida7e815762014-06-18 13:08:59 +00005492 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005493 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005494 if (ResTy == MatchOperand_NoMatch) {
5495 reportParseError("expected register containing function address");
5496 Parser.eatToEndOfStatement();
5497 return false;
5498 }
5499
5500 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5501 if (!FuncRegOpnd.isGPRAsmReg()) {
5502 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
5503 Parser.eatToEndOfStatement();
5504 return false;
5505 }
5506
5507 FuncReg = FuncRegOpnd.getGPR32Reg();
5508 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005509
Toma Tabacu65f10572014-09-16 15:00:52 +00005510 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005511 return true;
5512
Toma Tabacu13964452014-09-04 13:23:44 +00005513 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005514 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00005515 const MCExpr *OffsetExpr;
5516 int64_t OffsetVal;
5517 SMLoc ExprLoc = getLexer().getLoc();
5518
5519 if (Parser.parseExpression(OffsetExpr) ||
5520 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
5521 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00005522 Parser.eatToEndOfStatement();
5523 return false;
5524 }
Daniel Sanders5d796282015-09-21 09:26:55 +00005525
5526 Save = OffsetVal;
5527 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00005528 } else {
5529 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5530 if (!SaveOpnd.isGPRAsmReg()) {
5531 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
5532 Parser.eatToEndOfStatement();
5533 return false;
5534 }
5535 Save = SaveOpnd.getGPR32Reg();
5536 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005537
Toma Tabacu65f10572014-09-16 15:00:52 +00005538 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005539 return true;
5540
Toma Tabacu8874eac2015-02-18 13:46:53 +00005541 const MCExpr *Expr;
5542 if (Parser.parseExpression(Expr)) {
5543 reportParseError("expected expression");
5544 return false;
5545 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005546
Toma Tabacu8874eac2015-02-18 13:46:53 +00005547 if (Expr->getKind() != MCExpr::SymbolRef) {
5548 reportParseError("expected symbol");
5549 return false;
5550 }
5551 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
5552
Daniel Sandersf173dda2015-09-22 10:50:09 +00005553 CpSaveLocation = Save;
5554 CpSaveLocationIsRegister = SaveIsReg;
5555
Toma Tabacu8874eac2015-02-18 13:46:53 +00005556 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
5557 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005558 return false;
5559}
5560
Daniel Sandersf173dda2015-09-22 10:50:09 +00005561bool MipsAsmParser::parseDirectiveCPReturn() {
5562 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
5563 CpSaveLocationIsRegister);
5564 return false;
5565}
5566
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005567bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005568 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005569 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5570 const AsmToken &Tok = Parser.getTok();
5571
5572 if (Tok.getString() == "2008") {
5573 Parser.Lex();
5574 getTargetStreamer().emitDirectiveNaN2008();
5575 return false;
5576 } else if (Tok.getString() == "legacy") {
5577 Parser.Lex();
5578 getTargetStreamer().emitDirectiveNaNLegacy();
5579 return false;
5580 }
5581 }
5582 // If we don't recognize the option passed to the .nan
5583 // directive (e.g. no option or unknown option), emit an error.
5584 reportParseError("invalid option in .nan directive");
5585 return false;
5586}
5587
Jack Carter0b744b32012-10-04 02:29:46 +00005588bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005589 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005590 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00005591 const AsmToken &Tok = Parser.getTok();
5592
5593 if (Tok.getString() == "noat") {
5594 return parseSetNoAtDirective();
5595 } else if (Tok.getString() == "at") {
5596 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00005597 } else if (Tok.getString() == "arch") {
5598 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005599 } else if (Tok.getString() == "fp") {
5600 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005601 } else if (Tok.getString() == "oddspreg") {
5602 return parseSetOddSPRegDirective();
5603 } else if (Tok.getString() == "nooddspreg") {
5604 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005605 } else if (Tok.getString() == "pop") {
5606 return parseSetPopDirective();
5607 } else if (Tok.getString() == "push") {
5608 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00005609 } else if (Tok.getString() == "reorder") {
5610 return parseSetReorderDirective();
5611 } else if (Tok.getString() == "noreorder") {
5612 return parseSetNoReorderDirective();
5613 } else if (Tok.getString() == "macro") {
5614 return parseSetMacroDirective();
5615 } else if (Tok.getString() == "nomacro") {
5616 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00005617 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00005618 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005619 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00005620 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005621 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00005622 getTargetStreamer().emitDirectiveSetNoMicroMips();
5623 Parser.eatToEndOfStatement();
5624 return false;
5625 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005626 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00005627 } else if (Tok.getString() == "mips0") {
5628 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00005629 } else if (Tok.getString() == "mips1") {
5630 return parseSetFeature(Mips::FeatureMips1);
5631 } else if (Tok.getString() == "mips2") {
5632 return parseSetFeature(Mips::FeatureMips2);
5633 } else if (Tok.getString() == "mips3") {
5634 return parseSetFeature(Mips::FeatureMips3);
5635 } else if (Tok.getString() == "mips4") {
5636 return parseSetFeature(Mips::FeatureMips4);
5637 } else if (Tok.getString() == "mips5") {
5638 return parseSetFeature(Mips::FeatureMips5);
5639 } else if (Tok.getString() == "mips32") {
5640 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00005641 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005642 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005643 } else if (Tok.getString() == "mips32r3") {
5644 return parseSetFeature(Mips::FeatureMips32r3);
5645 } else if (Tok.getString() == "mips32r5") {
5646 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005647 } else if (Tok.getString() == "mips32r6") {
5648 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005649 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005650 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005651 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005652 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005653 } else if (Tok.getString() == "mips64r3") {
5654 return parseSetFeature(Mips::FeatureMips64r3);
5655 } else if (Tok.getString() == "mips64r5") {
5656 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005657 } else if (Tok.getString() == "mips64r6") {
5658 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00005659 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005660 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005661 } else if (Tok.getString() == "nodsp") {
5662 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00005663 } else if (Tok.getString() == "msa") {
5664 return parseSetMsaDirective();
5665 } else if (Tok.getString() == "nomsa") {
5666 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00005667 } else if (Tok.getString() == "softfloat") {
5668 return parseSetSoftFloatDirective();
5669 } else if (Tok.getString() == "hardfloat") {
5670 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00005671 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00005672 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00005673 parseSetAssignment();
5674 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005675 }
Jack Carter07c818d2013-01-25 01:31:34 +00005676
Jack Carter0b744b32012-10-04 02:29:46 +00005677 return true;
5678}
5679
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005680/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00005681/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005682bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005683 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005684 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5685 for (;;) {
5686 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005687 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00005688 return true;
5689
5690 getParser().getStreamer().EmitValue(Value, Size);
5691
5692 if (getLexer().is(AsmToken::EndOfStatement))
5693 break;
5694
Jack Carter07c818d2013-01-25 01:31:34 +00005695 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005696 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00005697 Parser.Lex();
5698 }
5699 }
5700
5701 Parser.Lex();
5702 return false;
5703}
5704
Vladimir Medic4c299852013-11-06 11:27:05 +00005705/// parseDirectiveGpWord
5706/// ::= .gpword local_sym
5707bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005708 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00005709 const MCExpr *Value;
5710 // EmitGPRel32Value requires an expression, so we are using base class
5711 // method to evaluate the expression.
5712 if (getParser().parseExpression(Value))
5713 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00005714 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00005715
Vladimir Medice10c1122013-11-13 13:18:04 +00005716 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005717 return Error(getLexer().getLoc(),
5718 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00005719 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00005720 return false;
5721}
5722
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005723/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00005724/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005725bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005726 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005727 const MCExpr *Value;
5728 // EmitGPRel64Value requires an expression, so we are using base class
5729 // method to evaluate the expression.
5730 if (getParser().parseExpression(Value))
5731 return true;
5732 getParser().getStreamer().EmitGPRel64Value(Value);
5733
5734 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005735 return Error(getLexer().getLoc(),
5736 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00005737 Parser.Lex(); // Eat EndOfStatement token.
5738 return false;
5739}
5740
Jack Carter0cd3c192014-01-06 23:27:31 +00005741bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005742 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00005743 // Get the option token.
5744 AsmToken Tok = Parser.getTok();
5745 // At the moment only identifiers are supported.
5746 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005747 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00005748 Parser.eatToEndOfStatement();
5749 return false;
5750 }
5751
5752 StringRef Option = Tok.getIdentifier();
5753
5754 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005755 // MipsAsmParser needs to know if the current PIC mode changes.
5756 IsPicEnabled = false;
5757
Jack Carter0cd3c192014-01-06 23:27:31 +00005758 getTargetStreamer().emitDirectiveOptionPic0();
5759 Parser.Lex();
5760 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5761 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005762 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005763 Parser.eatToEndOfStatement();
5764 }
5765 return false;
5766 }
5767
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005768 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005769 // MipsAsmParser needs to know if the current PIC mode changes.
5770 IsPicEnabled = true;
5771
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005772 getTargetStreamer().emitDirectiveOptionPic2();
5773 Parser.Lex();
5774 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5775 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005776 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005777 Parser.eatToEndOfStatement();
5778 }
5779 return false;
5780 }
5781
Jack Carter0cd3c192014-01-06 23:27:31 +00005782 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00005783 Warning(Parser.getTok().getLoc(),
5784 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00005785 Parser.eatToEndOfStatement();
5786 return false;
5787}
5788
Toma Tabacu9ca50962015-04-16 09:53:47 +00005789/// parseInsnDirective
5790/// ::= .insn
5791bool MipsAsmParser::parseInsnDirective() {
5792 // If this is not the end of the statement, report an error.
5793 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5794 reportParseError("unexpected token, expected end of statement");
5795 return false;
5796 }
5797
5798 // The actual label marking happens in
5799 // MipsELFStreamer::createPendingLabelRelocs().
5800 getTargetStreamer().emitDirectiveInsn();
5801
5802 getParser().Lex(); // Eat EndOfStatement token.
5803 return false;
5804}
5805
Simon Atanasyanbe186202016-02-11 06:45:54 +00005806/// parseSSectionDirective
5807/// ::= .sbss
5808/// ::= .sdata
5809bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) {
5810 // If this is not the end of the statement, report an error.
5811 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5812 reportParseError("unexpected token, expected end of statement");
5813 return false;
5814 }
5815
5816 MCSection *ELFSection = getContext().getELFSection(
5817 Section, Type, ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL);
5818 getParser().getStreamer().SwitchSection(ELFSection);
5819
5820 getParser().Lex(); // Eat EndOfStatement token.
5821 return false;
5822}
5823
Daniel Sanders7e527422014-07-10 13:38:23 +00005824/// parseDirectiveModule
5825/// ::= .module oddspreg
5826/// ::= .module nooddspreg
5827/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00005828/// ::= .module softfloat
5829/// ::= .module hardfloat
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005830bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005831 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005832 MCAsmLexer &Lexer = getLexer();
5833 SMLoc L = Lexer.getLoc();
5834
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00005835 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005836 // TODO : get a better message.
5837 reportParseError(".module directive must appear before any code");
5838 return false;
5839 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005840
Toma Tabacuc405c822015-01-23 10:40:19 +00005841 StringRef Option;
5842 if (Parser.parseIdentifier(Option)) {
5843 reportParseError("expected .module option identifier");
5844 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005845 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005846
Toma Tabacuc405c822015-01-23 10:40:19 +00005847 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005848 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005849
Toma Tabacu3c499582015-06-25 10:56:57 +00005850 // Synchronize the abiflags information with the FeatureBits information we
5851 // changed above.
5852 getTargetStreamer().updateABIInfo(*this);
5853
5854 // If printing assembly, use the recently updated abiflags information.
5855 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5856 // emitted at the end).
5857 getTargetStreamer().emitDirectiveModuleOddSPReg();
5858
Toma Tabacuc405c822015-01-23 10:40:19 +00005859 // If this is not the end of the statement, report an error.
5860 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5861 reportParseError("unexpected token, expected end of statement");
5862 return false;
5863 }
5864
5865 return false; // parseDirectiveModule has finished successfully.
5866 } else if (Option == "nooddspreg") {
5867 if (!isABI_O32()) {
5868 Error(L, "'.module nooddspreg' requires the O32 ABI");
5869 return false;
5870 }
5871
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005872 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005873
Toma Tabacu3c499582015-06-25 10:56:57 +00005874 // Synchronize the abiflags information with the FeatureBits information we
5875 // changed above.
5876 getTargetStreamer().updateABIInfo(*this);
5877
5878 // If printing assembly, use the recently updated abiflags information.
5879 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5880 // emitted at the end).
5881 getTargetStreamer().emitDirectiveModuleOddSPReg();
5882
Toma Tabacuc405c822015-01-23 10:40:19 +00005883 // If this is not the end of the statement, report an error.
5884 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5885 reportParseError("unexpected token, expected end of statement");
5886 return false;
5887 }
5888
5889 return false; // parseDirectiveModule has finished successfully.
5890 } else if (Option == "fp") {
5891 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00005892 } else if (Option == "softfloat") {
5893 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5894
5895 // Synchronize the ABI Flags information with the FeatureBits information we
5896 // updated above.
5897 getTargetStreamer().updateABIInfo(*this);
5898
5899 // If printing assembly, use the recently updated ABI Flags information.
5900 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5901 // emitted later).
5902 getTargetStreamer().emitDirectiveModuleSoftFloat();
5903
5904 // If this is not the end of the statement, report an error.
5905 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5906 reportParseError("unexpected token, expected end of statement");
5907 return false;
5908 }
5909
5910 return false; // parseDirectiveModule has finished successfully.
5911 } else if (Option == "hardfloat") {
5912 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5913
5914 // Synchronize the ABI Flags information with the FeatureBits information we
5915 // updated above.
5916 getTargetStreamer().updateABIInfo(*this);
5917
5918 // If printing assembly, use the recently updated ABI Flags information.
5919 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5920 // emitted later).
5921 getTargetStreamer().emitDirectiveModuleHardFloat();
5922
5923 // If this is not the end of the statement, report an error.
5924 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5925 reportParseError("unexpected token, expected end of statement");
5926 return false;
5927 }
5928
5929 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00005930 } else {
5931 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
5932 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005933}
5934
5935/// parseDirectiveModuleFP
5936/// ::= =32
5937/// ::= =xx
5938/// ::= =64
5939bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005940 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005941 MCAsmLexer &Lexer = getLexer();
5942
5943 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005944 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005945 return false;
5946 }
5947 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005948
Daniel Sanders7e527422014-07-10 13:38:23 +00005949 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005950 if (!parseFpABIValue(FpABI, ".module"))
5951 return false;
5952
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005953 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005954 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005955 return false;
5956 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005957
Toma Tabacua64e5402015-06-25 12:44:38 +00005958 // Synchronize the abiflags information with the FeatureBits information we
5959 // changed above.
5960 getTargetStreamer().updateABIInfo(*this);
5961
5962 // If printing assembly, use the recently updated abiflags information.
5963 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5964 // emitted at the end).
5965 getTargetStreamer().emitDirectiveModuleFP();
5966
Daniel Sanders7e527422014-07-10 13:38:23 +00005967 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005968 return false;
5969}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005970
Daniel Sanders7e527422014-07-10 13:38:23 +00005971bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005972 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005973 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005974 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005975 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005976
5977 if (Lexer.is(AsmToken::Identifier)) {
5978 StringRef Value = Parser.getTok().getString();
5979 Parser.Lex();
5980
5981 if (Value != "xx") {
5982 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5983 return false;
5984 }
5985
5986 if (!isABI_O32()) {
5987 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
5988 return false;
5989 }
5990
Daniel Sanders7e527422014-07-10 13:38:23 +00005991 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005992 if (ModuleLevelOptions) {
5993 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5994 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5995 } else {
5996 setFeatureBits(Mips::FeatureFPXX, "fpxx");
5997 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5998 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005999 return true;
6000 }
6001
6002 if (Lexer.is(AsmToken::Integer)) {
6003 unsigned Value = Parser.getTok().getIntVal();
6004 Parser.Lex();
6005
6006 if (Value != 32 && Value != 64) {
6007 reportParseError("unsupported value, expected 'xx', '32' or '64'");
6008 return false;
6009 }
6010
6011 if (Value == 32) {
6012 if (!isABI_O32()) {
6013 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
6014 return false;
6015 }
6016
Daniel Sanders7e527422014-07-10 13:38:23 +00006017 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006018 if (ModuleLevelOptions) {
6019 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6020 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6021 } else {
6022 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
6023 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
6024 }
Toma Tabacua64e5402015-06-25 12:44:38 +00006025 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00006026 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006027 if (ModuleLevelOptions) {
6028 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6029 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6030 } else {
6031 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
6032 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
6033 }
Toma Tabacua64e5402015-06-25 12:44:38 +00006034 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006035
Daniel Sanders7e527422014-07-10 13:38:23 +00006036 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006037 }
6038
6039 return false;
6040}
6041
Jack Carter0b744b32012-10-04 02:29:46 +00006042bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006043 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00006044 StringRef IDVal = DirectiveID.getString();
6045
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006046 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00006047 return parseDirectiveCpLoad(DirectiveID.getLoc());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006048 if (IDVal == ".cprestore")
6049 return parseDirectiveCpRestore(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00006050 if (IDVal == ".dword") {
6051 parseDataDirective(8, DirectiveID.getLoc());
6052 return false;
6053 }
Jack Carterd0bd6422013-04-18 00:41:53 +00006054 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006055 StringRef SymbolName;
6056
6057 if (Parser.parseIdentifier(SymbolName)) {
6058 reportParseError("expected identifier after .ent");
6059 return false;
6060 }
6061
6062 // There's an undocumented extension that allows an integer to
6063 // follow the name of the procedure which AFAICS is ignored by GAS.
6064 // Example: .ent foo,2
6065 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6066 if (getLexer().isNot(AsmToken::Comma)) {
6067 // Even though we accept this undocumented extension for compatibility
6068 // reasons, the additional integer argument does not actually change
6069 // the behaviour of the '.ent' directive, so we would like to discourage
6070 // its use. We do this by not referring to the extended version in
6071 // error messages which are not directly related to its use.
6072 reportParseError("unexpected token, expected end of statement");
6073 return false;
6074 }
6075 Parser.Lex(); // Eat the comma.
6076 const MCExpr *DummyNumber;
6077 int64_t DummyNumberVal;
6078 // If the user was explicitly trying to use the extended version,
6079 // we still give helpful extension-related error messages.
6080 if (Parser.parseExpression(DummyNumber)) {
6081 reportParseError("expected number after comma");
6082 return false;
6083 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00006084 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006085 reportParseError("expected an absolute expression after comma");
6086 return false;
6087 }
6088 }
6089
6090 // If this is not the end of the statement, report an error.
6091 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6092 reportParseError("unexpected token, expected end of statement");
6093 return false;
6094 }
6095
Jim Grosbach6f482002015-05-18 18:43:14 +00006096 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006097
6098 getTargetStreamer().emitDirectiveEnt(*Sym);
6099 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006100 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006101 return false;
6102 }
6103
Jack Carter07c818d2013-01-25 01:31:34 +00006104 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006105 StringRef SymbolName;
6106
6107 if (Parser.parseIdentifier(SymbolName)) {
6108 reportParseError("expected identifier after .end");
6109 return false;
6110 }
6111
6112 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6113 reportParseError("unexpected token, expected end of statement");
6114 return false;
6115 }
6116
6117 if (CurrentFn == nullptr) {
6118 reportParseError(".end used without .ent");
6119 return false;
6120 }
6121
6122 if ((SymbolName != CurrentFn->getName())) {
6123 reportParseError(".end symbol does not match .ent symbol");
6124 return false;
6125 }
6126
6127 getTargetStreamer().emitDirectiveEnd(SymbolName);
6128 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006129 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006130 return false;
6131 }
6132
Jack Carter07c818d2013-01-25 01:31:34 +00006133 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006134 // .frame $stack_reg, frame_size_in_bytes, $return_reg
6135 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00006136 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006137 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6138 reportParseError("expected stack register");
6139 return false;
6140 }
6141
6142 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6143 if (!StackRegOpnd.isGPRAsmReg()) {
6144 reportParseError(StackRegOpnd.getStartLoc(),
6145 "expected general purpose register");
6146 return false;
6147 }
6148 unsigned StackReg = StackRegOpnd.getGPR32Reg();
6149
6150 if (Parser.getTok().is(AsmToken::Comma))
6151 Parser.Lex();
6152 else {
6153 reportParseError("unexpected token, expected comma");
6154 return false;
6155 }
6156
6157 // Parse the frame size.
6158 const MCExpr *FrameSize;
6159 int64_t FrameSizeVal;
6160
6161 if (Parser.parseExpression(FrameSize)) {
6162 reportParseError("expected frame size value");
6163 return false;
6164 }
6165
Jim Grosbach13760bd2015-05-30 01:25:56 +00006166 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006167 reportParseError("frame size not an absolute expression");
6168 return false;
6169 }
6170
6171 if (Parser.getTok().is(AsmToken::Comma))
6172 Parser.Lex();
6173 else {
6174 reportParseError("unexpected token, expected comma");
6175 return false;
6176 }
6177
6178 // Parse the return register.
6179 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00006180 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006181 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6182 reportParseError("expected return register");
6183 return false;
6184 }
6185
6186 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6187 if (!ReturnRegOpnd.isGPRAsmReg()) {
6188 reportParseError(ReturnRegOpnd.getStartLoc(),
6189 "expected general purpose register");
6190 return false;
6191 }
6192
6193 // If this is not the end of the statement, report an error.
6194 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6195 reportParseError("unexpected token, expected end of statement");
6196 return false;
6197 }
6198
6199 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
6200 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006201 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006202 return false;
6203 }
6204
Jack Carter07c818d2013-01-25 01:31:34 +00006205 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00006206 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00006207 }
6208
Daniel Sandersd97a6342014-08-13 10:07:34 +00006209 if (IDVal == ".mask" || IDVal == ".fmask") {
6210 // .mask bitmask, frame_offset
6211 // bitmask: One bit for each register used.
6212 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
6213 // first register is expected to be saved.
6214 // Examples:
6215 // .mask 0x80000000, -4
6216 // .fmask 0x80000000, -4
6217 //
Jack Carterbe332172012-09-07 00:48:02 +00006218
Daniel Sandersd97a6342014-08-13 10:07:34 +00006219 // Parse the bitmask
6220 const MCExpr *BitMask;
6221 int64_t BitMaskVal;
6222
6223 if (Parser.parseExpression(BitMask)) {
6224 reportParseError("expected bitmask value");
6225 return false;
6226 }
6227
Jim Grosbach13760bd2015-05-30 01:25:56 +00006228 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006229 reportParseError("bitmask not an absolute expression");
6230 return false;
6231 }
6232
6233 if (Parser.getTok().is(AsmToken::Comma))
6234 Parser.Lex();
6235 else {
6236 reportParseError("unexpected token, expected comma");
6237 return false;
6238 }
6239
6240 // Parse the frame_offset
6241 const MCExpr *FrameOffset;
6242 int64_t FrameOffsetVal;
6243
6244 if (Parser.parseExpression(FrameOffset)) {
6245 reportParseError("expected frame offset value");
6246 return false;
6247 }
6248
Jim Grosbach13760bd2015-05-30 01:25:56 +00006249 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006250 reportParseError("frame offset not an absolute expression");
6251 return false;
6252 }
6253
6254 // If this is not the end of the statement, report an error.
6255 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6256 reportParseError("unexpected token, expected end of statement");
6257 return false;
6258 }
6259
6260 if (IDVal == ".mask")
6261 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
6262 else
6263 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00006264 return false;
6265 }
6266
Matheus Almeida0051f2d2014-04-16 15:48:55 +00006267 if (IDVal == ".nan")
6268 return parseDirectiveNaN();
6269
Jack Carter07c818d2013-01-25 01:31:34 +00006270 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00006271 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00006272 return false;
6273 }
6274
Rafael Espindolab59fb732014-03-28 18:50:26 +00006275 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00006276 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00006277 return false;
6278 }
6279
Jack Carter07c818d2013-01-25 01:31:34 +00006280 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00006281 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00006282 return false;
6283 }
6284
Scott Egertond1aeb052016-02-15 16:11:51 +00006285 if (IDVal == ".hword") {
6286 parseDataDirective(2, DirectiveID.getLoc());
6287 return false;
6288 }
6289
Jack Carter0cd3c192014-01-06 23:27:31 +00006290 if (IDVal == ".option")
6291 return parseDirectiveOption();
6292
6293 if (IDVal == ".abicalls") {
6294 getTargetStreamer().emitDirectiveAbiCalls();
6295 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006296 Error(Parser.getTok().getLoc(),
6297 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00006298 // Clear line
6299 Parser.eatToEndOfStatement();
6300 }
6301 return false;
6302 }
6303
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006304 if (IDVal == ".cpsetup")
6305 return parseDirectiveCPSetup();
6306
Daniel Sandersf173dda2015-09-22 10:50:09 +00006307 if (IDVal == ".cpreturn")
6308 return parseDirectiveCPReturn();
6309
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006310 if (IDVal == ".module")
6311 return parseDirectiveModule();
6312
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00006313 if (IDVal == ".llvm_internal_mips_reallow_module_directive")
6314 return parseInternalDirectiveReallowModule();
6315
Toma Tabacu9ca50962015-04-16 09:53:47 +00006316 if (IDVal == ".insn")
6317 return parseInsnDirective();
6318
Simon Atanasyanbe186202016-02-11 06:45:54 +00006319 if (IDVal == ".sbss")
6320 return parseSSectionDirective(IDVal, ELF::SHT_NOBITS);
6321 if (IDVal == ".sdata")
6322 return parseSSectionDirective(IDVal, ELF::SHT_PROGBITS);
6323
Rafael Espindola870c4e92012-01-11 03:56:41 +00006324 return true;
6325}
6326
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00006327bool MipsAsmParser::parseInternalDirectiveReallowModule() {
6328 // If this is not the end of the statement, report an error.
6329 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6330 reportParseError("unexpected token, expected end of statement");
6331 return false;
6332 }
6333
6334 getTargetStreamer().reallowModuleDirective();
6335
6336 getParser().Lex(); // Eat EndOfStatement token.
6337 return false;
6338}
6339
Rafael Espindola870c4e92012-01-11 03:56:41 +00006340extern "C" void LLVMInitializeMipsAsmParser() {
6341 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
6342 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
6343 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
6344 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
6345}
Jack Carterb4dbc172012-09-05 23:34:03 +00006346
6347#define GET_REGISTER_MATCHER
6348#define GET_MATCHER_IMPLEMENTATION
6349#include "MipsGenAsmMatcher.inc"