blob: 2d98fa02e117a35278b1d53e041fa537b6fa2593 [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>
Daniel Sanders85fd10b2016-03-31 14:34:00 +0000951 void addSImmOperands(MCInst &Inst, unsigned N) const {
952 if (isImm() && !isConstantImm()) {
953 addExpr(Inst, getImm());
954 return;
955 }
956 addConstantSImmOperands<Bits, 0, 0>(Inst, N);
957 }
958
959 template <unsigned Bits>
Daniel Sandersf8bb23e2016-02-01 15:13:31 +0000960 void addUImmOperands(MCInst &Inst, unsigned N) const {
961 if (isImm() && !isConstantImm()) {
962 addExpr(Inst, getImm());
963 return;
964 }
965 addConstantUImmOperands<Bits, 0, 0>(Inst, N);
966 }
967
Daniel Sanders78e89022016-03-11 11:37:50 +0000968 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
969 void addConstantSImmOperands(MCInst &Inst, unsigned N) const {
970 assert(N == 1 && "Invalid number of operands!");
971 int64_t Imm = getConstantImm() - Offset;
972 Imm = SignExtend64<Bits>(Imm);
973 Imm += Offset;
974 Imm += AdjustOffset;
975 Inst.addOperand(MCOperand::createImm(Imm));
976 }
977
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000978 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000979 assert(N == 1 && "Invalid number of operands!");
980 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000981 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000982 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000983
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000984 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000985 assert(N == 2 && "Invalid number of operands!");
986
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000987 Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
988 ? getMemBase()->getGPR64Reg()
989 : getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000990
991 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000992 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000993 }
994
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000995 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
996 assert(N == 2 && "Invalid number of operands!");
997
Jim Grosbache9119e42015-05-13 18:37:00 +0000998 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000999
1000 const MCExpr *Expr = getMemOff();
1001 addExpr(Inst, Expr);
1002 }
1003
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001004 void addRegListOperands(MCInst &Inst, unsigned N) const {
1005 assert(N == 1 && "Invalid number of operands!");
1006
1007 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001008 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001009 }
1010
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001011 void addRegPairOperands(MCInst &Inst, unsigned N) const {
1012 assert(N == 2 && "Invalid number of operands!");
1013 unsigned RegNo = getRegPair();
Jim Grosbache9119e42015-05-13 18:37:00 +00001014 Inst.addOperand(MCOperand::createReg(RegNo++));
1015 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001016 }
1017
Zoran Jovanovic41688672015-02-10 16:36:20 +00001018 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
1019 assert(N == 2 && "Invalid number of operands!");
1020 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001021 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +00001022 }
1023
Craig Topper56c590a2014-04-29 07:58:02 +00001024 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001025 // As a special case until we sort out the definition of div/divu, pretend
1026 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
1027 if (isGPRAsmReg() && RegIdx.Index == 0)
1028 return true;
1029
1030 return Kind == k_PhysRegister;
1031 }
1032 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +00001033 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001034 bool isConstantImm() const {
Craig Topper66059c92015-11-18 07:07:59 +00001035 return isImm() && isa<MCConstantExpr>(getImm());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001036 }
Daniel Sanders52da7af2015-11-06 12:11:03 +00001037 bool isConstantImmz() const {
1038 return isConstantImm() && getConstantImm() == 0;
1039 }
Daniel Sandersea4f6532015-11-06 12:22:31 +00001040 template <unsigned Bits, int Offset = 0> bool isConstantUImm() const {
1041 return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset);
1042 }
Daniel Sanders85fd10b2016-03-31 14:34:00 +00001043 template <unsigned Bits> bool isSImm() const {
1044 return isConstantImm() ? isInt<Bits>(getConstantImm()) : isImm();
1045 }
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001046 template <unsigned Bits> bool isUImm() const {
1047 return isConstantImm() ? isUInt<Bits>(getConstantImm()) : isImm();
1048 }
1049 template <unsigned Bits> bool isAnyImm() const {
1050 return isConstantImm() ? (isInt<Bits>(getConstantImm()) ||
1051 isUInt<Bits>(getConstantImm()))
1052 : isImm();
1053 }
Daniel Sanders78e89022016-03-11 11:37:50 +00001054 template <unsigned Bits, int Offset = 0> bool isConstantSImm() const {
1055 return isConstantImm() && isInt<Bits>(getConstantImm() - Offset);
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +00001056 }
Hrvoje Varga46458d02016-02-25 12:53:29 +00001057 template <unsigned Bottom, unsigned Top> bool isConstantUImmRange() const {
1058 return isConstantImm() && getConstantImm() >= Bottom &&
1059 getConstantImm() <= Top;
1060 }
Craig Topper56c590a2014-04-29 07:58:02 +00001061 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001062 // Note: It's not possible to pretend that other operand kinds are tokens.
1063 // The matcher emitter checks tokens first.
1064 return Kind == k_Token;
1065 }
Craig Topper56c590a2014-04-29 07:58:02 +00001066 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001067 bool isConstantMemOff() const {
Craig Topper66059c92015-11-18 07:07:59 +00001068 return isMem() && isa<MCConstantExpr>(getMemOff());
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001069 }
Daniel Sandersdc0602a2016-03-31 14:12:01 +00001070 template <unsigned Bits, unsigned ShiftAmount = 0>
1071 bool isMemWithSimmOffset() const {
1072 return isMem() && isConstantMemOff() &&
1073 isShiftedInt<Bits, ShiftAmount>(getConstantMemOff()) &&
1074 getMemBase()->isGPRAsmReg();
Zoran Jovanovica6593ff2015-08-18 12:53:08 +00001075 }
Zoran Jovanovic6e6a2c92015-09-16 09:14:35 +00001076 template <unsigned Bits> bool isMemWithSimmOffsetGPR() const {
1077 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff()) &&
1078 getMemBase()->isGPRAsmReg();
1079 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001080 bool isMemWithGRPMM16Base() const {
1081 return isMem() && getMemBase()->isMM16AsmReg();
1082 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001083 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
1084 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1085 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
1086 }
Jozef Kolek12c69822014-12-23 16:16:33 +00001087 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
1088 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1089 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1090 && (getMemBase()->getGPR32Reg() == Mips::SP);
1091 }
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001092 template <unsigned Bits, unsigned ShiftLeftAmount>
1093 bool isScaledUImm() const {
1094 return isConstantImm() &&
1095 isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm());
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00001096 }
Daniel Sanders97297772016-03-22 14:40:00 +00001097 template <unsigned Bits, unsigned ShiftLeftAmount>
1098 bool isScaledSImm() const {
1099 return isConstantImm() &&
1100 isShiftedInt<Bits, ShiftLeftAmount>(getConstantImm());
1101 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001102 bool isRegList16() const {
1103 if (!isRegList())
1104 return false;
1105
1106 int Size = RegList.List->size();
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001107 if (Size < 2 || Size > 5)
1108 return false;
1109
1110 unsigned R0 = RegList.List->front();
1111 unsigned R1 = RegList.List->back();
1112 if (!((R0 == Mips::S0 && R1 == Mips::RA) ||
1113 (R0 == Mips::S0_64 && R1 == Mips::RA_64)))
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001114 return false;
1115
1116 int PrevReg = *RegList.List->begin();
1117 for (int i = 1; i < Size - 1; i++) {
1118 int Reg = (*(RegList.List))[i];
1119 if ( Reg != PrevReg + 1)
1120 return false;
1121 PrevReg = Reg;
1122 }
1123
1124 return true;
1125 }
Vladimir Medic2b953d02013-10-01 09:48:56 +00001126 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001127 bool isLSAImm() const {
1128 if (!isConstantImm())
1129 return false;
1130 int64_t Val = getConstantImm();
1131 return 1 <= Val && Val <= 4;
1132 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001133 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001134 bool isMovePRegPair() const {
1135 if (Kind != k_RegList || RegList.List->size() != 2)
1136 return false;
1137
1138 unsigned R0 = RegList.List->front();
1139 unsigned R1 = RegList.List->back();
1140
1141 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
1142 (R0 == Mips::A1 && R1 == Mips::A3) ||
1143 (R0 == Mips::A2 && R1 == Mips::A3) ||
1144 (R0 == Mips::A0 && R1 == Mips::S5) ||
1145 (R0 == Mips::A0 && R1 == Mips::S6) ||
1146 (R0 == Mips::A0 && R1 == Mips::A1) ||
1147 (R0 == Mips::A0 && R1 == Mips::A2) ||
1148 (R0 == Mips::A0 && R1 == Mips::A3))
1149 return true;
1150
1151 return false;
1152 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001153
1154 StringRef getToken() const {
1155 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001156 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001157 }
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001158 bool isRegPair() const { return Kind == k_RegPair; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001159
Craig Topper56c590a2014-04-29 07:58:02 +00001160 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001161 // As a special case until we sort out the definition of div/divu, pretend
1162 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
1163 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1164 RegIdx.Kind & RegKind_GPR)
1165 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001166
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001167 assert(Kind == k_PhysRegister && "Invalid access!");
1168 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +00001169 }
1170
Jack Carterb4dbc172012-09-05 23:34:03 +00001171 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001172 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001173 return Imm.Val;
1174 }
1175
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001176 int64_t getConstantImm() const {
1177 const MCExpr *Val = getImm();
1178 return static_cast<const MCConstantExpr *>(Val)->getValue();
1179 }
1180
1181 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001182 assert((Kind == k_Memory) && "Invalid access!");
1183 return Mem.Base;
1184 }
1185
1186 const MCExpr *getMemOff() const {
1187 assert((Kind == k_Memory) && "Invalid access!");
1188 return Mem.Off;
1189 }
1190
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001191 int64_t getConstantMemOff() const {
1192 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1193 }
1194
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001195 const SmallVectorImpl<unsigned> &getRegList() const {
1196 assert((Kind == k_RegList) && "Invalid access!");
1197 return *(RegList.List);
1198 }
1199
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001200 unsigned getRegPair() const {
1201 assert((Kind == k_RegPair) && "Invalid access!");
1202 return RegIdx.Index;
1203 }
1204
David Blaikie960ea3f2014-06-08 16:18:35 +00001205 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1206 MipsAsmParser &Parser) {
1207 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001208 Op->Tok.Data = Str.data();
1209 Op->Tok.Length = Str.size();
1210 Op->StartLoc = S;
1211 Op->EndLoc = S;
1212 return Op;
1213 }
1214
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001215 /// Create a numeric register (e.g. $1). The exact register remains
1216 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001217 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001218 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001219 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001220 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001221 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001222 }
1223
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001224 /// Create a register that is definitely a GPR.
1225 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001226 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001227 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001228 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001229 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001230 }
1231
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001232 /// Create a register that is definitely a FGR.
1233 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001234 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001235 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001236 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001237 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
1238 }
1239
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001240 /// Create a register that is definitely a HWReg.
1241 /// This is typically only used for named registers such as $hwr_cpunum.
1242 static std::unique_ptr<MipsOperand>
1243 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
1244 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1245 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
1246 }
1247
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001248 /// Create a register that is definitely an FCC.
1249 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001250 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001251 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001252 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001253 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
1254 }
1255
1256 /// Create a register that is definitely an ACC.
1257 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001258 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001259 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001260 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001261 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
1262 }
1263
1264 /// Create a register that is definitely an MSA128.
1265 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001266 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001267 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001268 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001269 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
1270 }
1271
1272 /// Create a register that is definitely an MSACtrl.
1273 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001274 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001275 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001276 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001277 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
1278 }
1279
David Blaikie960ea3f2014-06-08 16:18:35 +00001280 static std::unique_ptr<MipsOperand>
1281 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1282 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001283 Op->Imm.Val = Val;
1284 Op->StartLoc = S;
1285 Op->EndLoc = E;
1286 return Op;
1287 }
1288
David Blaikie960ea3f2014-06-08 16:18:35 +00001289 static std::unique_ptr<MipsOperand>
1290 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1291 SMLoc E, MipsAsmParser &Parser) {
1292 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1293 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001294 Op->Mem.Off = Off;
1295 Op->StartLoc = S;
1296 Op->EndLoc = E;
1297 return Op;
1298 }
1299
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001300 static std::unique_ptr<MipsOperand>
1301 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1302 MipsAsmParser &Parser) {
1303 assert (Regs.size() > 0 && "Empty list not allowed");
1304
1305 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001306 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001307 Op->StartLoc = StartLoc;
1308 Op->EndLoc = EndLoc;
1309 return Op;
1310 }
1311
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001312 static std::unique_ptr<MipsOperand>
1313 CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1314 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
1315 Op->RegIdx.Index = RegNo;
1316 Op->StartLoc = S;
1317 Op->EndLoc = E;
1318 return Op;
1319 }
1320
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001321 bool isGPRAsmReg() const {
1322 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001323 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001324 bool isMM16AsmReg() const {
1325 if (!(isRegIdx() && RegIdx.Kind))
1326 return false;
1327 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1328 || RegIdx.Index == 16 || RegIdx.Index == 17);
1329 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001330 bool isMM16AsmRegZero() const {
1331 if (!(isRegIdx() && RegIdx.Kind))
1332 return false;
1333 return (RegIdx.Index == 0 ||
1334 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1335 RegIdx.Index == 17);
1336 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001337 bool isMM16AsmRegMoveP() const {
1338 if (!(isRegIdx() && RegIdx.Kind))
1339 return false;
1340 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1341 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1342 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001343 bool isFGRAsmReg() const {
1344 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1345 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001346 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001347 bool isHWRegsAsmReg() const {
1348 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001349 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001350 bool isCCRAsmReg() const {
1351 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001352 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001353 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001354 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1355 return false;
1356 if (!AsmParser.hasEightFccRegisters())
1357 return RegIdx.Index == 0;
1358 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001359 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001360 bool isACCAsmReg() const {
1361 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001362 }
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001363 bool isCOP0AsmReg() const {
1364 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1365 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001366 bool isCOP2AsmReg() const {
1367 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001368 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001369 bool isCOP3AsmReg() const {
1370 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1371 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001372 bool isMSA128AsmReg() const {
1373 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001374 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001375 bool isMSACtrlAsmReg() const {
1376 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001377 }
1378
Jack Carterb4dbc172012-09-05 23:34:03 +00001379 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001380 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001381 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001382 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001383
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001384 virtual ~MipsOperand() {
1385 switch (Kind) {
1386 case k_Immediate:
1387 break;
1388 case k_Memory:
1389 delete Mem.Base;
1390 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001391 case k_RegList:
1392 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001393 case k_PhysRegister:
1394 case k_RegisterIndex:
1395 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001396 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001397 break;
1398 }
1399 }
1400
Craig Topper56c590a2014-04-29 07:58:02 +00001401 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001402 switch (Kind) {
1403 case k_Immediate:
1404 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001405 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001406 OS << ">";
1407 break;
1408 case k_Memory:
1409 OS << "Mem<";
1410 Mem.Base->print(OS);
1411 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001412 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001413 OS << ">";
1414 break;
1415 case k_PhysRegister:
1416 OS << "PhysReg<" << PhysReg.Num << ">";
1417 break;
1418 case k_RegisterIndex:
1419 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1420 break;
1421 case k_Token:
1422 OS << Tok.Data;
1423 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001424 case k_RegList:
1425 OS << "RegList< ";
1426 for (auto Reg : (*RegList.List))
1427 OS << Reg << " ";
1428 OS << ">";
1429 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001430 case k_RegPair:
1431 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1432 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001433 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001434 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001435}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001436} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001437
Jack Carter9e65aa32013-03-22 00:05:30 +00001438namespace llvm {
1439extern const MCInstrDesc MipsInsts[];
1440}
1441static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1442 return MipsInsts[Opcode];
1443}
1444
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001445static bool hasShortDelaySlot(unsigned Opcode) {
1446 switch (Opcode) {
1447 case Mips::JALS_MM:
1448 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001449 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001450 case Mips::BGEZALS_MM:
1451 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001452 return true;
1453 default:
1454 return false;
1455 }
1456}
1457
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001458static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1459 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1460 return &SRExpr->getSymbol();
1461 }
1462
1463 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1464 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1465 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1466
1467 if (LHSSym)
1468 return LHSSym;
1469
1470 if (RHSSym)
1471 return RHSSym;
1472
1473 return nullptr;
1474 }
1475
1476 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1477 return getSingleMCSymbol(UExpr->getSubExpr());
1478
1479 return nullptr;
1480}
1481
1482static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1483 if (isa<MCSymbolRefExpr>(Expr))
1484 return 1;
1485
1486 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1487 return countMCSymbolRefExpr(BExpr->getLHS()) +
1488 countMCSymbolRefExpr(BExpr->getRHS());
1489
1490 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1491 return countMCSymbolRefExpr(UExpr->getSubExpr());
1492
1493 return 0;
1494}
1495
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001496namespace {
1497void emitRX(unsigned Opcode, unsigned Reg0, MCOperand Op1, SMLoc IDLoc,
1498 SmallVectorImpl<MCInst> &Instructions) {
1499 MCInst tmpInst;
1500 tmpInst.setOpcode(Opcode);
1501 tmpInst.addOperand(MCOperand::createReg(Reg0));
1502 tmpInst.addOperand(Op1);
1503 tmpInst.setLoc(IDLoc);
1504 Instructions.push_back(tmpInst);
1505}
1506
1507void emitRI(unsigned Opcode, unsigned Reg0, int32_t Imm, SMLoc IDLoc,
1508 SmallVectorImpl<MCInst> &Instructions) {
1509 emitRX(Opcode, Reg0, MCOperand::createImm(Imm), IDLoc, Instructions);
1510}
1511
1512void emitRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, SMLoc IDLoc,
1513 SmallVectorImpl<MCInst> &Instructions) {
1514 emitRX(Opcode, Reg0, MCOperand::createReg(Reg1), IDLoc, Instructions);
1515}
1516
1517void emitII(unsigned Opcode, int16_t Imm1, int16_t Imm2, SMLoc IDLoc,
1518 SmallVectorImpl<MCInst> &Instructions) {
1519 MCInst tmpInst;
1520 tmpInst.setOpcode(Opcode);
1521 tmpInst.addOperand(MCOperand::createImm(Imm1));
1522 tmpInst.addOperand(MCOperand::createImm(Imm2));
1523 tmpInst.setLoc(IDLoc);
1524 Instructions.push_back(tmpInst);
1525}
1526
1527void emitR(unsigned Opcode, unsigned Reg0, SMLoc IDLoc,
1528 SmallVectorImpl<MCInst> &Instructions) {
1529 MCInst tmpInst;
1530 tmpInst.setOpcode(Opcode);
1531 tmpInst.addOperand(MCOperand::createReg(Reg0));
1532 tmpInst.setLoc(IDLoc);
1533 Instructions.push_back(tmpInst);
1534}
1535
1536void emitRRX(unsigned Opcode, unsigned Reg0, unsigned Reg1, MCOperand Op2,
1537 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1538 MCInst tmpInst;
1539 tmpInst.setOpcode(Opcode);
1540 tmpInst.addOperand(MCOperand::createReg(Reg0));
1541 tmpInst.addOperand(MCOperand::createReg(Reg1));
1542 tmpInst.addOperand(Op2);
1543 tmpInst.setLoc(IDLoc);
1544 Instructions.push_back(tmpInst);
1545}
1546
1547void emitRRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, unsigned Reg2,
1548 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1549 emitRRX(Opcode, Reg0, Reg1, MCOperand::createReg(Reg2), IDLoc,
1550 Instructions);
1551}
1552
1553void emitRRI(unsigned Opcode, unsigned Reg0, unsigned Reg1, int16_t Imm,
1554 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1555 emitRRX(Opcode, Reg0, Reg1, MCOperand::createImm(Imm), IDLoc,
1556 Instructions);
1557}
1558
1559void emitAppropriateDSLL(unsigned DstReg, unsigned SrcReg, int16_t ShiftAmount,
1560 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1561 if (ShiftAmount >= 32) {
1562 emitRRI(Mips::DSLL32, DstReg, SrcReg, ShiftAmount - 32, IDLoc,
1563 Instructions);
1564 return;
1565 }
1566
1567 emitRRI(Mips::DSLL, DstReg, SrcReg, ShiftAmount, IDLoc, Instructions);
1568}
1569} // end anonymous namespace.
1570
Jack Carter9e65aa32013-03-22 00:05:30 +00001571bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001572 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001573 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001574 bool ExpandedJalSym = false;
Daniel Sandersa771fef2014-03-24 14:05:39 +00001575
Jack Carter9e65aa32013-03-22 00:05:30 +00001576 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001577
1578 if (MCID.isBranch() || MCID.isCall()) {
1579 const unsigned Opcode = Inst.getOpcode();
1580 MCOperand Offset;
1581
1582 switch (Opcode) {
1583 default:
1584 break;
Kai Nackee0245392015-01-27 19:11:28 +00001585 case Mips::BBIT0:
1586 case Mips::BBIT032:
1587 case Mips::BBIT1:
1588 case Mips::BBIT132:
1589 assert(hasCnMips() && "instruction only valid for octeon cpus");
1590 // Fall through
1591
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001592 case Mips::BEQ:
1593 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001594 case Mips::BEQ_MM:
1595 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001596 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001597 Offset = Inst.getOperand(2);
1598 if (!Offset.isImm())
1599 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001600 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001601 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001602 if (OffsetToAlignment(Offset.getImm(),
1603 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001604 return Error(IDLoc, "branch to misaligned address");
1605 break;
1606 case Mips::BGEZ:
1607 case Mips::BGTZ:
1608 case Mips::BLEZ:
1609 case Mips::BLTZ:
1610 case Mips::BGEZAL:
1611 case Mips::BLTZAL:
1612 case Mips::BC1F:
1613 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001614 case Mips::BGEZ_MM:
1615 case Mips::BGTZ_MM:
1616 case Mips::BLEZ_MM:
1617 case Mips::BLTZ_MM:
1618 case Mips::BGEZAL_MM:
1619 case Mips::BLTZAL_MM:
1620 case Mips::BC1F_MM:
1621 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001622 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001623 Offset = Inst.getOperand(1);
1624 if (!Offset.isImm())
1625 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001626 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001627 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001628 if (OffsetToAlignment(Offset.getImm(),
1629 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001630 return Error(IDLoc, "branch to misaligned address");
1631 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001632 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001633 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001634 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001635 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001636 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1637 Offset = Inst.getOperand(1);
1638 if (!Offset.isImm())
1639 break; // We'll deal with this situation later on when applying fixups.
Craig Topper55b1f292015-10-10 20:17:07 +00001640 if (!isInt<8>(Offset.getImm()))
Jozef Kolek9761e962015-01-12 12:03:34 +00001641 return Error(IDLoc, "branch target out of range");
1642 if (OffsetToAlignment(Offset.getImm(), 2LL))
1643 return Error(IDLoc, "branch to misaligned address");
1644 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001645 }
1646 }
1647
Daniel Sandersa84989a2014-06-16 13:25:35 +00001648 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1649 // We still accept it but it is a normal nop.
1650 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1651 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1652 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1653 "nop instruction");
1654 }
1655
Kai Nackee0245392015-01-27 19:11:28 +00001656 if (hasCnMips()) {
1657 const unsigned Opcode = Inst.getOpcode();
1658 MCOperand Opnd;
1659 int Imm;
1660
1661 switch (Opcode) {
1662 default:
1663 break;
1664
1665 case Mips::BBIT0:
1666 case Mips::BBIT032:
1667 case Mips::BBIT1:
1668 case Mips::BBIT132:
1669 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1670 // The offset is handled above
1671 Opnd = Inst.getOperand(1);
1672 if (!Opnd.isImm())
1673 return Error(IDLoc, "expected immediate operand kind");
1674 Imm = Opnd.getImm();
1675 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1676 Opcode == Mips::BBIT1 ? 63 : 31))
1677 return Error(IDLoc, "immediate operand value out of range");
1678 if (Imm > 31) {
1679 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1680 : Mips::BBIT132);
1681 Inst.getOperand(1).setImm(Imm - 32);
1682 }
1683 break;
1684
Kai Nackee0245392015-01-27 19:11:28 +00001685 case Mips::SEQi:
1686 case Mips::SNEi:
1687 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1688 Opnd = Inst.getOperand(2);
1689 if (!Opnd.isImm())
1690 return Error(IDLoc, "expected immediate operand kind");
1691 Imm = Opnd.getImm();
1692 if (!isInt<10>(Imm))
1693 return Error(IDLoc, "immediate operand value out of range");
1694 break;
1695 }
1696 }
1697
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001698 // This expansion is not in a function called by tryExpandInstruction()
1699 // because the pseudo-instruction doesn't have a distinct opcode.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001700 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
1701 inPicMode()) {
1702 warnIfNoMacro(IDLoc);
1703
1704 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
1705
1706 // We can do this expansion if there's only 1 symbol in the argument
1707 // expression.
1708 if (countMCSymbolRefExpr(JalExpr) > 1)
1709 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
1710
1711 // FIXME: This is checking the expression can be handled by the later stages
1712 // of the assembler. We ought to leave it to those later stages but
1713 // we can't do that until we stop evaluateRelocExpr() rewriting the
1714 // expressions into non-equivalent forms.
1715 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
1716
1717 // FIXME: Add support for label+offset operands (currently causes an error).
1718 // FIXME: Add support for forward-declared local symbols.
1719 // FIXME: Add expansion for when the LargeGOT option is enabled.
1720 if (JalSym->isInSection() || JalSym->isTemporary()) {
1721 if (isABI_O32()) {
1722 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001723 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001724 // R_(MICRO)MIPS_GOT16 label
1725 // addiu $25, $25, 0
1726 // R_(MICRO)MIPS_LO16 label
1727 // jalr $25
1728 const MCExpr *Got16RelocExpr = evaluateRelocExpr(JalExpr, "got");
1729 const MCExpr *Lo16RelocExpr = evaluateRelocExpr(JalExpr, "lo");
1730
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001731 emitRRX(Mips::LW, Mips::T9, Mips::GP,
1732 MCOperand::createExpr(Got16RelocExpr), IDLoc, Instructions);
1733 emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
1734 MCOperand::createExpr(Lo16RelocExpr), IDLoc, Instructions);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001735 } else if (isABI_N32() || isABI_N64()) {
1736 // If it's a local symbol and the N32/N64 ABIs are being used,
1737 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001738 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001739 // R_(MICRO)MIPS_GOT_DISP label
1740 // jalr $25
1741 const MCExpr *GotDispRelocExpr = evaluateRelocExpr(JalExpr, "got_disp");
1742
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001743 emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
1744 MCOperand::createExpr(GotDispRelocExpr), IDLoc, Instructions);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001745 }
1746 } else {
Daniel Sandersb7002032015-11-20 13:16:35 +00001747 // If it's an external/weak symbol, we expand to:
1748 // lw/ld $25, 0($gp)
1749 // R_(MICRO)MIPS_CALL16 label
1750 // jalr $25
1751 const MCExpr *Call16RelocExpr = evaluateRelocExpr(JalExpr, "call16");
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001752
Daniel Sandersb7002032015-11-20 13:16:35 +00001753 emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
1754 MCOperand::createExpr(Call16RelocExpr), IDLoc, Instructions);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001755 }
1756
1757 MCInst JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001758 if (IsCpRestoreSet && inMicroMipsMode())
1759 JalrInst.setOpcode(Mips::JALRS_MM);
1760 else
1761 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001762 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
1763 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
1764
1765 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
1766 // This relocation is supposed to be an optimization hint for the linker
1767 // and is not necessary for correctness.
1768
1769 Inst = JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001770 ExpandedJalSym = true;
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001771 }
1772
Jack Carter9e65aa32013-03-22 00:05:30 +00001773 if (MCID.mayLoad() || MCID.mayStore()) {
1774 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001775 // reference or immediate we may have to expand instructions.
1776 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001777 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001778 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1779 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001780 MCOperand &Op = Inst.getOperand(i);
1781 if (Op.isImm()) {
1782 int MemOffset = Op.getImm();
1783 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001784 // Offset can't exceed 16bit value.
1785 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001786 return false;
1787 }
1788 } else if (Op.isExpr()) {
1789 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001790 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001791 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001792 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001793 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001794 // Expand symbol.
1795 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001796 return false;
1797 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001798 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001799 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001800 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001801 }
1802 }
1803 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001804 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001805 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001806
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001807 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001808 if (MCID.mayLoad()) {
1809 // Try to create 16-bit GP relative load instruction.
1810 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1811 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1812 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1813 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1814 MCOperand &Op = Inst.getOperand(i);
1815 if (Op.isImm()) {
1816 int MemOffset = Op.getImm();
1817 MCOperand &DstReg = Inst.getOperand(0);
1818 MCOperand &BaseReg = Inst.getOperand(1);
Craig Topper55b1f292015-10-10 20:17:07 +00001819 if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&
Jozef Koleke10a02e2015-01-28 17:27:26 +00001820 getContext().getRegisterInfo()->getRegClass(
1821 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00001822 (BaseReg.getReg() == Mips::GP ||
1823 BaseReg.getReg() == Mips::GP_64)) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001824
1825 emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
1826 IDLoc, Instructions);
Jozef Koleke10a02e2015-01-28 17:27:26 +00001827 return false;
1828 }
1829 }
1830 }
1831 } // for
1832 } // if load
1833
1834 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1835
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001836 MCOperand Opnd;
1837 int Imm;
1838
1839 switch (Inst.getOpcode()) {
1840 default:
1841 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001842 case Mips::ADDIUSP_MM:
1843 Opnd = Inst.getOperand(0);
1844 if (!Opnd.isImm())
1845 return Error(IDLoc, "expected immediate operand kind");
1846 Imm = Opnd.getImm();
1847 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1848 Imm % 4 != 0)
1849 return Error(IDLoc, "immediate operand value out of range");
1850 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001851 case Mips::SLL16_MM:
1852 case Mips::SRL16_MM:
1853 Opnd = Inst.getOperand(2);
1854 if (!Opnd.isImm())
1855 return Error(IDLoc, "expected immediate operand kind");
1856 Imm = Opnd.getImm();
1857 if (Imm < 1 || Imm > 8)
1858 return Error(IDLoc, "immediate operand value out of range");
1859 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001860 case Mips::LI16_MM:
1861 Opnd = Inst.getOperand(1);
1862 if (!Opnd.isImm())
1863 return Error(IDLoc, "expected immediate operand kind");
1864 Imm = Opnd.getImm();
1865 if (Imm < -1 || Imm > 126)
1866 return Error(IDLoc, "immediate operand value out of range");
1867 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001868 case Mips::ADDIUR2_MM:
1869 Opnd = Inst.getOperand(2);
1870 if (!Opnd.isImm())
1871 return Error(IDLoc, "expected immediate operand kind");
1872 Imm = Opnd.getImm();
1873 if (!(Imm == 1 || Imm == -1 ||
1874 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1875 return Error(IDLoc, "immediate operand value out of range");
1876 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001877 case Mips::ANDI16_MM:
1878 Opnd = Inst.getOperand(2);
1879 if (!Opnd.isImm())
1880 return Error(IDLoc, "expected immediate operand kind");
1881 Imm = Opnd.getImm();
1882 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1883 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1884 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1885 return Error(IDLoc, "immediate operand value out of range");
1886 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001887 case Mips::LBU16_MM:
1888 Opnd = Inst.getOperand(2);
1889 if (!Opnd.isImm())
1890 return Error(IDLoc, "expected immediate operand kind");
1891 Imm = Opnd.getImm();
1892 if (Imm < -1 || Imm > 14)
1893 return Error(IDLoc, "immediate operand value out of range");
1894 break;
1895 case Mips::SB16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001896 case Mips::SB16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001897 Opnd = Inst.getOperand(2);
1898 if (!Opnd.isImm())
1899 return Error(IDLoc, "expected immediate operand kind");
1900 Imm = Opnd.getImm();
1901 if (Imm < 0 || Imm > 15)
1902 return Error(IDLoc, "immediate operand value out of range");
1903 break;
1904 case Mips::LHU16_MM:
1905 case Mips::SH16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001906 case Mips::SH16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001907 Opnd = Inst.getOperand(2);
1908 if (!Opnd.isImm())
1909 return Error(IDLoc, "expected immediate operand kind");
1910 Imm = Opnd.getImm();
1911 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1912 return Error(IDLoc, "immediate operand value out of range");
1913 break;
1914 case Mips::LW16_MM:
1915 case Mips::SW16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001916 case Mips::SW16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001917 Opnd = Inst.getOperand(2);
1918 if (!Opnd.isImm())
1919 return Error(IDLoc, "expected immediate operand kind");
1920 Imm = Opnd.getImm();
1921 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1922 return Error(IDLoc, "immediate operand value out of range");
1923 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001924 case Mips::ADDIUPC_MM:
1925 MCOperand Opnd = Inst.getOperand(1);
1926 if (!Opnd.isImm())
1927 return Error(IDLoc, "expected immediate operand kind");
1928 int Imm = Opnd.getImm();
Craig Topper55b1f292015-10-10 20:17:07 +00001929 if ((Imm % 4 != 0) || !isInt<25>(Imm))
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001930 return Error(IDLoc, "immediate operand value out of range");
1931 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001932 }
1933 }
1934
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001935 MacroExpanderResultTy ExpandResult =
1936 tryExpandInstruction(Inst, IDLoc, Instructions);
1937 switch (ExpandResult) {
1938 case MER_NotAMacro:
Jack Carter9e65aa32013-03-22 00:05:30 +00001939 Instructions.push_back(Inst);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001940 break;
1941 case MER_Success:
1942 break;
1943 case MER_Fail:
1944 return true;
1945 }
Jack Carter9e65aa32013-03-22 00:05:30 +00001946
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001947 // If this instruction has a delay slot and .set reorder is active,
1948 // emit a NOP after it.
1949 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
1950 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1951
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001952 if ((Inst.getOpcode() == Mips::JalOneReg ||
1953 Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
1954 isPicAndNotNxxAbi()) {
1955 if (IsCpRestoreSet) {
1956 // We need a NOP between the JALR and the LW:
1957 // If .set reorder has been used, we've already emitted a NOP.
1958 // If .set noreorder has been used, we need to emit a NOP at this point.
1959 if (!AssemblerOptions.back()->isReorder())
1960 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1961
1962 // Load the $gp from the stack.
1963 SmallVector<MCInst, 3> LoadInsts;
1964 createCpRestoreMemOp(true /*IsLoad*/, CpRestoreOffset /*StackOffset*/,
1965 IDLoc, LoadInsts);
1966
1967 for (const MCInst &Inst : LoadInsts)
1968 Instructions.push_back(Inst);
1969
1970 } else
1971 Warning(IDLoc, "no .cprestore used in PIC mode");
1972 }
1973
Jack Carter9e65aa32013-03-22 00:05:30 +00001974 return false;
1975}
1976
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001977MipsAsmParser::MacroExpanderResultTy
1978MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
1979 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001980 switch (Inst.getOpcode()) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001981 default:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001982 return MER_NotAMacro;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001983 case Mips::LoadImm32:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001984 return expandLoadImm(Inst, true, IDLoc, Instructions) ? MER_Fail
1985 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001986 case Mips::LoadImm64:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001987 return expandLoadImm(Inst, false, IDLoc, Instructions) ? MER_Fail
1988 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001989 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001990 case Mips::LoadAddrImm64:
1991 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1992 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
1993 "expected immediate operand kind");
1994
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001995 return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,
1996 Inst.getOperand(1),
1997 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,
1998 Instructions)
1999 ? MER_Fail
2000 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002001 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002002 case Mips::LoadAddrReg64:
2003 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2004 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2005 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
2006 "expected immediate operand kind");
2007
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002008 return expandLoadAddress(Inst.getOperand(0).getReg(),
2009 Inst.getOperand(1).getReg(), Inst.getOperand(2),
2010 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,
2011 Instructions)
2012 ? MER_Fail
2013 : MER_Success;
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002014 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00002015 case Mips::B_MMR6_Pseudo:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002016 return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions) ? MER_Fail
2017 : MER_Success;
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002018 case Mips::SWM_MM:
2019 case Mips::LWM_MM:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002020 return expandLoadStoreMultiple(Inst, IDLoc, Instructions) ? MER_Fail
2021 : MER_Success;
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002022 case Mips::JalOneReg:
2023 case Mips::JalTwoReg:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002024 return expandJalWithRegs(Inst, IDLoc, Instructions) ? MER_Fail
2025 : MER_Success;
Toma Tabacue1e460d2015-06-11 10:36:10 +00002026 case Mips::BneImm:
2027 case Mips::BeqImm:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002028 return expandBranchImm(Inst, IDLoc, Instructions) ? MER_Fail : MER_Success;
Toma Tabacu1a108322015-06-17 13:20:24 +00002029 case Mips::BLT:
2030 case Mips::BLE:
2031 case Mips::BGE:
2032 case Mips::BGT:
2033 case Mips::BLTU:
2034 case Mips::BLEU:
2035 case Mips::BGEU:
2036 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002037 case Mips::BLTL:
2038 case Mips::BLEL:
2039 case Mips::BGEL:
2040 case Mips::BGTL:
2041 case Mips::BLTUL:
2042 case Mips::BLEUL:
2043 case Mips::BGEUL:
2044 case Mips::BGTUL:
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002045 case Mips::BLTImmMacro:
2046 case Mips::BLEImmMacro:
2047 case Mips::BGEImmMacro:
2048 case Mips::BGTImmMacro:
2049 case Mips::BLTUImmMacro:
2050 case Mips::BLEUImmMacro:
2051 case Mips::BGEUImmMacro:
2052 case Mips::BGTUImmMacro:
2053 case Mips::BLTLImmMacro:
2054 case Mips::BLELImmMacro:
2055 case Mips::BGELImmMacro:
2056 case Mips::BGTLImmMacro:
2057 case Mips::BLTULImmMacro:
2058 case Mips::BLEULImmMacro:
2059 case Mips::BGEULImmMacro:
2060 case Mips::BGTULImmMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002061 return expandCondBranches(Inst, IDLoc, Instructions) ? MER_Fail
2062 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002063 case Mips::SDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002064 return expandDiv(Inst, IDLoc, Instructions, false, true) ? MER_Fail
2065 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002066 case Mips::DSDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002067 return expandDiv(Inst, IDLoc, Instructions, true, true) ? MER_Fail
2068 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002069 case Mips::UDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002070 return expandDiv(Inst, IDLoc, Instructions, false, false) ? MER_Fail
2071 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002072 case Mips::DUDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002073 return expandDiv(Inst, IDLoc, Instructions, true, false) ? MER_Fail
2074 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002075 case Mips::PseudoTRUNC_W_S:
2076 return expandTrunc(Inst, false, false, IDLoc, Instructions) ? MER_Fail
2077 : MER_Success;
2078 case Mips::PseudoTRUNC_W_D32:
2079 return expandTrunc(Inst, true, false, IDLoc, Instructions) ? MER_Fail
2080 : MER_Success;
2081 case Mips::PseudoTRUNC_W_D:
2082 return expandTrunc(Inst, true, true, IDLoc, Instructions) ? MER_Fail
2083 : MER_Success;
Daniel Sanders6394ee52015-10-15 14:52:58 +00002084 case Mips::Ulh:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002085 return expandUlh(Inst, true, IDLoc, Instructions) ? MER_Fail : MER_Success;
Toma Tabacud88d79c2015-06-23 14:39:42 +00002086 case Mips::Ulhu:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002087 return expandUlh(Inst, false, IDLoc, Instructions) ? MER_Fail : MER_Success;
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00002088 case Mips::Ulw:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002089 return expandUlw(Inst, IDLoc, Instructions) ? MER_Fail : MER_Success;
2090 case Mips::NORImm:
2091 return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail
2092 : MER_Success;
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002093 case Mips::ADDi:
2094 case Mips::ADDiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002095 case Mips::SLTi:
2096 case Mips::SLTiu:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002097 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2098 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2099 int64_t ImmValue = Inst.getOperand(2).getImm();
2100 if (isInt<16>(ImmValue))
2101 return MER_NotAMacro;
2102 return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail
2103 : MER_Success;
2104 }
2105 return MER_NotAMacro;
2106 case Mips::ANDi:
2107 case Mips::ORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002108 case Mips::XORi:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002109 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2110 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2111 int64_t ImmValue = Inst.getOperand(2).getImm();
2112 if (isUInt<16>(ImmValue))
2113 return MER_NotAMacro;
2114 return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail
2115 : MER_Success;
2116 }
2117 return MER_NotAMacro;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002118 case Mips::ROL:
2119 case Mips::ROR:
2120 return expandRotation(Inst, IDLoc, Instructions) ? MER_Fail
2121 : MER_Success;
2122 case Mips::ROLImm:
2123 case Mips::RORImm:
2124 return expandRotationImm(Inst, IDLoc, Instructions) ? MER_Fail
2125 : MER_Success;
2126 case Mips::DROL:
2127 case Mips::DROR:
2128 return expandDRotation(Inst, IDLoc, Instructions) ? MER_Fail
2129 : MER_Success;
2130 case Mips::DROLImm:
2131 case Mips::DRORImm:
2132 return expandDRotationImm(Inst, IDLoc, Instructions) ? MER_Fail
2133 : MER_Success;
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00002134 case Mips::ABSMacro:
2135 return expandAbs(Inst, IDLoc, Instructions) ? MER_Fail
2136 : MER_Success;
Jack Carterd0bd6422013-04-18 00:41:53 +00002137 }
Jack Carter30a59822012-10-04 04:03:53 +00002138}
Jack Carter92995f12012-10-06 00:53:28 +00002139
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002140bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
2141 SmallVectorImpl<MCInst> &Instructions) {
2142 // Create a JALR instruction which is going to replace the pseudo-JAL.
2143 MCInst JalrInst;
2144 JalrInst.setLoc(IDLoc);
2145 const MCOperand FirstRegOp = Inst.getOperand(0);
2146 const unsigned Opcode = Inst.getOpcode();
2147
2148 if (Opcode == Mips::JalOneReg) {
2149 // jal $rs => jalr $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002150 if (IsCpRestoreSet && inMicroMipsMode()) {
2151 JalrInst.setOpcode(Mips::JALRS16_MM);
2152 JalrInst.addOperand(FirstRegOp);
2153 } else if (inMicroMipsMode()) {
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002154 JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002155 JalrInst.addOperand(FirstRegOp);
2156 } else {
2157 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002158 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002159 JalrInst.addOperand(FirstRegOp);
2160 }
2161 } else if (Opcode == Mips::JalTwoReg) {
2162 // jal $rd, $rs => jalr $rd, $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002163 if (IsCpRestoreSet && inMicroMipsMode())
2164 JalrInst.setOpcode(Mips::JALRS_MM);
2165 else
2166 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002167 JalrInst.addOperand(FirstRegOp);
2168 const MCOperand SecondRegOp = Inst.getOperand(1);
2169 JalrInst.addOperand(SecondRegOp);
2170 }
2171 Instructions.push_back(JalrInst);
2172
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002173 // If .set reorder is active and branch instruction has a delay slot,
2174 // emit a NOP after it.
2175 const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
2176 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) {
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002177 createNop(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc, Instructions);
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002178 }
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002179
2180 return false;
2181}
2182
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002183/// Can the value be represented by a unsigned N-bit value and a shift left?
Benjamin Kramer039b1042015-10-28 13:54:36 +00002184template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002185 unsigned BitNum = findFirstSet(x);
2186
2187 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2188}
2189
2190/// Load (or add) an immediate into a register.
2191///
2192/// @param ImmValue The immediate to load.
2193/// @param DstReg The register that will hold the immediate.
2194/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2195/// for a simple initialization.
2196/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2197/// @param IsAddress True if the immediate represents an address. False if it
2198/// is an integer.
2199/// @param IDLoc Location of the immediate in the source file.
2200/// @param Instructions The instructions emitted by this expansion.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002201bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002202 unsigned SrcReg, bool Is32BitImm,
2203 bool IsAddress, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00002204 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu00e98672015-05-01 12:19:27 +00002205 if (!Is32BitImm && !isGP64bit()) {
2206 Error(IDLoc, "instruction requires a 64-bit architecture");
2207 return true;
2208 }
2209
Daniel Sanders03f9c012015-07-14 12:24:22 +00002210 if (Is32BitImm) {
2211 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2212 // Sign extend up to 64-bit so that the predicates match the hardware
2213 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2214 // true.
2215 ImmValue = SignExtend64<32>(ImmValue);
2216 } else {
2217 Error(IDLoc, "instruction requires a 32-bit immediate");
2218 return true;
2219 }
2220 }
2221
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002222 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2223 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2224
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002225 bool UseSrcReg = false;
2226 if (SrcReg != Mips::NoRegister)
2227 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002228
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002229 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002230 if (UseSrcReg &&
2231 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002232 // At this point we need AT to perform the expansions and we exit if it is
2233 // not available.
2234 unsigned ATReg = getATReg(IDLoc);
2235 if (!ATReg)
2236 return true;
2237 TmpReg = ATReg;
2238 }
2239
Daniel Sanders03f9c012015-07-14 12:24:22 +00002240 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002241 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002242 SrcReg = ZeroReg;
2243
2244 // This doesn't quite follow the usual ABI expectations for N32 but matches
2245 // traditional assembler behaviour. N32 would normally use addiu for both
2246 // integers and addresses.
2247 if (IsAddress && !Is32BitImm) {
2248 emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
2249 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002250 }
2251
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002252 emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
2253 return false;
2254 }
2255
2256 if (isUInt<16>(ImmValue)) {
2257 unsigned TmpReg = DstReg;
2258 if (SrcReg == DstReg) {
2259 TmpReg = getATReg(IDLoc);
2260 if (!TmpReg)
2261 return true;
2262 }
2263
2264 emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002265 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002266 emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2267 return false;
2268 }
2269
2270 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002271 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002272
Toma Tabacu79588102015-04-29 10:19:56 +00002273 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2274 uint16_t Bits15To0 = ImmValue & 0xffff;
2275
Toma Tabacua3d056f2015-05-15 09:42:11 +00002276 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002277 // Traditional behaviour seems to special case this particular value. It's
2278 // not clear why other masks are handled differently.
2279 if (ImmValue == 0xffffffff) {
Daniel Sandersf1ae3672015-08-18 09:55:57 +00002280 emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, Instructions);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002281 emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, Instructions);
2282 if (UseSrcReg)
2283 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2284 return false;
2285 }
2286
2287 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002288 // upper 32 bits.
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002289 emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002290 emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, Instructions);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002291 if (Bits15To0)
2292 emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
2293 if (UseSrcReg)
2294 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2295 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002296 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002297
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002298 emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, Instructions);
2299 if (Bits15To0)
2300 emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002301 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002302 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2303 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002304 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002305
2306 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2307 if (Is32BitImm) {
2308 Error(IDLoc, "instruction requires a 32-bit immediate");
2309 return true;
2310 }
2311
2312 // Traditionally, these immediates are shifted as little as possible and as
2313 // such we align the most significant bit to bit 15 of our temporary.
2314 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2315 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2316 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2317 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
2318 emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, Instructions);
2319 emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, Instructions);
2320
2321 if (UseSrcReg)
2322 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2323
2324 return false;
2325 }
2326
2327 warnIfNoMacro(IDLoc);
2328
2329 // The remaining case is packed with a sequence of dsll and ori with zeros
2330 // being omitted and any neighbouring dsll's being coalesced.
2331 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2332
2333 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2334 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
2335 IDLoc, Instructions))
2336 return false;
2337
2338 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2339 // skip it and defer the shift to the next chunk.
2340 unsigned ShiftCarriedForwards = 16;
2341 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2342 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2343
2344 if (ImmChunk != 0) {
2345 emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
2346 Instructions);
2347 emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, Instructions);
2348 ShiftCarriedForwards = 0;
2349 }
2350
2351 ShiftCarriedForwards += 16;
2352 }
2353 ShiftCarriedForwards -= 16;
2354
2355 // Finish any remaining shifts left by trailing zeros.
2356 if (ShiftCarriedForwards)
2357 emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
2358 Instructions);
2359
2360 if (UseSrcReg)
2361 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2362
Matheus Almeida3813d572014-06-19 14:39:14 +00002363 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002364}
Jack Carter92995f12012-10-06 00:53:28 +00002365
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002366bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
2367 SmallVectorImpl<MCInst> &Instructions) {
2368 const MCOperand &ImmOp = Inst.getOperand(1);
2369 assert(ImmOp.isImm() && "expected immediate operand kind");
2370 const MCOperand &DstRegOp = Inst.getOperand(0);
2371 assert(DstRegOp.isReg() && "expected register operand kind");
2372
2373 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002374 Is32BitImm, false, IDLoc, Instructions))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002375 return true;
2376
2377 return false;
2378}
2379
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002380bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2381 const MCOperand &Offset,
2382 bool Is32BitAddress, SMLoc IDLoc,
2383 SmallVectorImpl<MCInst> &Instructions) {
2384 // la can't produce a usable address when addresses are 64-bit.
2385 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2386 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2387 // We currently can't do this because we depend on the equality
2388 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2389 Error(IDLoc, "la used to load 64-bit address");
2390 // Continue as if we had 'dla' instead.
2391 Is32BitAddress = false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002392 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002393
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002394 // dla requires 64-bit addresses.
Scott Egerton24557012016-01-21 15:11:01 +00002395 if (!Is32BitAddress && !hasMips3()) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002396 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002397 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002398 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002399
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002400 if (!Offset.isImm())
2401 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
2402 Is32BitAddress, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002403
Scott Egerton24557012016-01-21 15:11:01 +00002404 if (!ABI.ArePtrs64bit()) {
2405 // Continue as if we had 'la' whether we had 'la' or 'dla'.
2406 Is32BitAddress = true;
2407 }
2408
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002409 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
2410 IDLoc, Instructions);
Jack Carter543fdf82012-10-09 23:29:45 +00002411}
2412
Toma Tabacuf712ede2015-06-17 14:31:51 +00002413bool MipsAsmParser::loadAndAddSymbolAddress(
2414 const MCExpr *SymExpr, unsigned DstReg, unsigned SrcReg, bool Is32BitSym,
2415 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002416 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002417
Daniel Sandersd5a89412015-10-05 13:19:29 +00002418 const MCExpr *Symbol = cast<MCExpr>(SymExpr);
2419 const MipsMCExpr *HiExpr = MipsMCExpr::create(
2420 MCSymbolRefExpr::VK_Mips_ABS_HI, Symbol, getContext());
2421 const MipsMCExpr *LoExpr = MipsMCExpr::create(
2422 MCSymbolRefExpr::VK_Mips_ABS_LO, Symbol, getContext());
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002423
Toma Tabacufb9d1252015-06-22 12:08:39 +00002424 bool UseSrcReg = SrcReg != Mips::NoRegister;
2425
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002426 // This is the 64-bit symbol address expansion.
2427 if (ABI.ArePtrs64bit() && isGP64bit()) {
2428 // We always need AT for the 64-bit expansion.
2429 // If it is not available we exit.
2430 unsigned ATReg = getATReg(IDLoc);
2431 if (!ATReg)
2432 return true;
2433
Daniel Sandersd5a89412015-10-05 13:19:29 +00002434 const MipsMCExpr *HighestExpr = MipsMCExpr::create(
2435 MCSymbolRefExpr::VK_Mips_HIGHEST, Symbol, getContext());
2436 const MipsMCExpr *HigherExpr = MipsMCExpr::create(
2437 MCSymbolRefExpr::VK_Mips_HIGHER, Symbol, getContext());
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002438
Scott Egerton24557012016-01-21 15:11:01 +00002439 if (UseSrcReg &&
2440 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2441 SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002442 // If $rs is the same as $rd:
2443 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
2444 // daddiu $at, $at, %higher(sym)
2445 // dsll $at, $at, 16
2446 // daddiu $at, $at, %hi(sym)
2447 // dsll $at, $at, 16
2448 // daddiu $at, $at, %lo(sym)
2449 // daddu $rd, $at, $rd
2450 emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
2451 Instructions);
2452 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HigherExpr),
2453 IDLoc, Instructions);
2454 emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
2455 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
2456 Instructions);
2457 emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
2458 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
2459 Instructions);
2460 emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, Instructions);
2461
2462 return false;
2463 }
2464
2465 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2466 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
2467 // lui $at, %hi(sym)
2468 // daddiu $rd, $rd, %higher(sym)
2469 // daddiu $at, $at, %lo(sym)
2470 // dsll32 $rd, $rd, 0
2471 // daddu $rd, $rd, $at
2472 // (daddu $rd, $rd, $rs)
2473 emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
2474 Instructions);
2475 emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
2476 Instructions);
2477 emitRRX(Mips::DADDiu, DstReg, DstReg, MCOperand::createExpr(HigherExpr),
2478 IDLoc, Instructions);
2479 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
2480 Instructions);
2481 emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, Instructions);
2482 emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, Instructions);
2483 if (UseSrcReg)
2484 emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, Instructions);
2485
2486 return false;
2487 }
2488
2489 // And now, the 32-bit symbol address expansion:
2490 // If $rs is the same as $rd:
2491 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
2492 // ori $at, $at, %lo(sym)
2493 // addu $rd, $at, $rd
2494 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2495 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
2496 // ori $rd, $rd, %lo(sym)
2497 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00002498 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002499 if (UseSrcReg &&
2500 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002501 // If $rs is the same as $rd, we need to use AT.
2502 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00002503 unsigned ATReg = getATReg(IDLoc);
2504 if (!ATReg)
2505 return true;
2506 TmpReg = ATReg;
2507 }
2508
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002509 emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, Instructions);
2510 emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr), IDLoc,
2511 Instructions);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002512
Toma Tabacufb9d1252015-06-22 12:08:39 +00002513 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002514 emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2515 else
Scott Egerton24557012016-01-21 15:11:01 +00002516 assert(
2517 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, TmpReg));
Toma Tabacuf712ede2015-06-17 14:31:51 +00002518
Toma Tabacu674825c2015-06-16 12:16:24 +00002519 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002520}
2521
NAKAMURA Takumi2bbc90c2015-01-23 01:02:07 +00002522bool MipsAsmParser::expandUncondBranchMMPseudo(
2523 MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00002524 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
2525 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002526
2527 MCOperand Offset = Inst.getOperand(0);
2528 if (Offset.isExpr()) {
2529 Inst.clear();
2530 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002531 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2532 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2533 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002534 } else {
2535 assert(Offset.isImm() && "expected immediate operand kind");
Craig Topper55b1f292015-10-10 20:17:07 +00002536 if (isInt<11>(Offset.getImm())) {
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002537 // If offset fits into 11 bits then this instruction becomes microMIPS
2538 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00002539 if (inMicroMipsMode())
2540 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002541 } else {
Craig Topper55b1f292015-10-10 20:17:07 +00002542 if (!isInt<17>(Offset.getImm()))
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002543 Error(IDLoc, "branch target out of range");
2544 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
2545 Error(IDLoc, "branch to misaligned address");
2546 Inst.clear();
2547 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002548 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2549 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2550 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002551 }
2552 }
2553 Instructions.push_back(Inst);
2554
Zoran Jovanovicada70912015-09-07 11:56:37 +00002555 // If .set reorder is active and branch instruction has a delay slot,
2556 // emit a NOP after it.
2557 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
2558 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Toma Tabacu234482a2015-03-16 12:03:39 +00002559 createNop(true, IDLoc, Instructions);
2560
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002561 return false;
2562}
2563
Toma Tabacue1e460d2015-06-11 10:36:10 +00002564bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc,
2565 SmallVectorImpl<MCInst> &Instructions) {
2566 const MCOperand &DstRegOp = Inst.getOperand(0);
2567 assert(DstRegOp.isReg() && "expected register operand kind");
2568
2569 const MCOperand &ImmOp = Inst.getOperand(1);
2570 assert(ImmOp.isImm() && "expected immediate operand kind");
2571
2572 const MCOperand &MemOffsetOp = Inst.getOperand(2);
Daniel Sanders90f0d0b2016-02-29 11:24:49 +00002573 assert((MemOffsetOp.isImm() || MemOffsetOp.isExpr()) &&
2574 "expected immediate or expression operand");
Toma Tabacue1e460d2015-06-11 10:36:10 +00002575
2576 unsigned OpCode = 0;
2577 switch(Inst.getOpcode()) {
2578 case Mips::BneImm:
2579 OpCode = Mips::BNE;
2580 break;
2581 case Mips::BeqImm:
2582 OpCode = Mips::BEQ;
2583 break;
2584 default:
2585 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
2586 break;
2587 }
2588
2589 int64_t ImmValue = ImmOp.getImm();
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002590 if (ImmValue == 0)
2591 emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
2592 Instructions);
2593 else {
Toma Tabacue1e460d2015-06-11 10:36:10 +00002594 warnIfNoMacro(IDLoc);
2595
2596 unsigned ATReg = getATReg(IDLoc);
2597 if (!ATReg)
2598 return true;
2599
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002600 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
2601 IDLoc, Instructions))
Toma Tabacue1e460d2015-06-11 10:36:10 +00002602 return true;
2603
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002604 emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, Instructions);
Toma Tabacue1e460d2015-06-11 10:36:10 +00002605 }
2606 return false;
2607}
2608
Jack Carter9e65aa32013-03-22 00:05:30 +00002609void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00002610 SmallVectorImpl<MCInst> &Instructions,
2611 bool isLoad, bool isImmOpnd) {
Scott Egertond65377d2016-03-17 10:37:51 +00002612 MCOperand HiOperand, LoOperand;
Jack Carter9e65aa32013-03-22 00:05:30 +00002613 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00002614 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002615 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2616 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002617 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002618 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2619 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002620 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00002621 if (isImmOpnd) {
2622 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
Scott Egertond65377d2016-03-17 10:37:51 +00002623 unsigned ImmOffset = Inst.getOperand(2).getImm();
2624 unsigned LoOffset = ImmOffset & 0x0000ffff;
2625 unsigned HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00002626 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00002627 if (LoOffset & 0x8000)
2628 HiOffset++;
Scott Egertond65377d2016-03-17 10:37:51 +00002629 LoOperand = MCOperand::createImm(LoOffset);
2630 HiOperand = MCOperand::createImm(HiOffset);
2631 } else {
2632 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
2633 LoOperand = MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "lo"));
2634 HiOperand = MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "hi"));
2635 }
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002636 // These are some of the types of expansions we perform here:
2637 // 1) lw $8, sym => lui $8, %hi(sym)
2638 // lw $8, %lo(sym)($8)
2639 // 2) lw $8, offset($9) => lui $8, %hi(offset)
2640 // add $8, $8, $9
2641 // lw $8, %lo(offset)($9)
2642 // 3) lw $8, offset($8) => lui $at, %hi(offset)
2643 // add $at, $at, $8
2644 // lw $8, %lo(offset)($at)
2645 // 4) sw $8, sym => lui $at, %hi(sym)
2646 // sw $8, %lo(sym)($at)
2647 // 5) sw $8, offset($8) => lui $at, %hi(offset)
2648 // add $at, $at, $8
2649 // sw $8, %lo(offset)($at)
2650 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
2651 // ldc1 $f0, %lo(sym)($at)
2652 //
2653 // For load instructions we can use the destination register as a temporary
2654 // if base and dst are different (examples 1 and 2) and if the base register
2655 // is general purpose otherwise we must use $at (example 6) and error if it's
2656 // not available. For stores we must use $at (examples 4 and 5) because we
2657 // must not clobber the source register setting up the offset.
2658 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
2659 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
2660 unsigned RegClassIDOp0 =
2661 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
2662 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
2663 (RegClassIDOp0 == Mips::GPR64RegClassID);
2664 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00002665 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002666 else {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002667 // At this point we need AT to perform the expansions and we exit if it is
2668 // not available.
Toma Tabacu89a712b2015-04-15 10:48:56 +00002669 TmpRegNum = getATReg(IDLoc);
2670 if (!TmpRegNum)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002671 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002672 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002673
Scott Egertond65377d2016-03-17 10:37:51 +00002674 emitRX(Mips::LUi, TmpRegNum, HiOperand, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00002675 // Add temp register to base.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002676 if (BaseRegNum != Mips::ZERO)
2677 emitRRR(Mips::ADDu, TmpRegNum, TmpRegNum, BaseRegNum, IDLoc, Instructions);
Alp Tokercb402912014-01-24 17:20:08 +00002678 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00002679 // of offset and new base.
Scott Egertond65377d2016-03-17 10:37:51 +00002680 emitRRX(Inst.getOpcode(), RegOpNum, TmpRegNum, LoOperand, IDLoc, Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +00002681}
2682
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002683bool
2684MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2685 SmallVectorImpl<MCInst> &Instructions) {
2686 unsigned OpNum = Inst.getNumOperands();
2687 unsigned Opcode = Inst.getOpcode();
2688 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2689
2690 assert (Inst.getOperand(OpNum - 1).isImm() &&
2691 Inst.getOperand(OpNum - 2).isReg() &&
2692 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2693
2694 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2695 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002696 (Inst.getOperand(OpNum - 2).getReg() == Mips::SP ||
2697 Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) &&
2698 (Inst.getOperand(OpNum - 3).getReg() == Mips::RA ||
2699 Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002700 // It can be implemented as SWM16 or LWM16 instruction.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002701 if (inMicroMipsMode() && hasMips32r6())
2702 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6;
2703 else
2704 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2705 }
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002706
2707 Inst.setOpcode(NewOpcode);
2708 Instructions.push_back(Inst);
2709 return false;
2710}
2711
Toma Tabacu1a108322015-06-17 13:20:24 +00002712bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
2713 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002714 bool EmittedNoMacroWarning = false;
Toma Tabacu1a108322015-06-17 13:20:24 +00002715 unsigned PseudoOpcode = Inst.getOpcode();
2716 unsigned SrcReg = Inst.getOperand(0).getReg();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002717 const MCOperand &TrgOp = Inst.getOperand(1);
Toma Tabacu1a108322015-06-17 13:20:24 +00002718 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
2719
2720 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002721 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00002722
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002723 unsigned TrgReg;
2724 if (TrgOp.isReg())
2725 TrgReg = TrgOp.getReg();
2726 else if (TrgOp.isImm()) {
2727 warnIfNoMacro(IDLoc);
2728 EmittedNoMacroWarning = true;
2729
2730 TrgReg = getATReg(IDLoc);
2731 if (!TrgReg)
2732 return true;
2733
2734 switch(PseudoOpcode) {
2735 default:
2736 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2737 case Mips::BLTImmMacro:
2738 PseudoOpcode = Mips::BLT;
2739 break;
2740 case Mips::BLEImmMacro:
2741 PseudoOpcode = Mips::BLE;
2742 break;
2743 case Mips::BGEImmMacro:
2744 PseudoOpcode = Mips::BGE;
2745 break;
2746 case Mips::BGTImmMacro:
2747 PseudoOpcode = Mips::BGT;
2748 break;
2749 case Mips::BLTUImmMacro:
2750 PseudoOpcode = Mips::BLTU;
2751 break;
2752 case Mips::BLEUImmMacro:
2753 PseudoOpcode = Mips::BLEU;
2754 break;
2755 case Mips::BGEUImmMacro:
2756 PseudoOpcode = Mips::BGEU;
2757 break;
2758 case Mips::BGTUImmMacro:
2759 PseudoOpcode = Mips::BGTU;
2760 break;
2761 case Mips::BLTLImmMacro:
2762 PseudoOpcode = Mips::BLTL;
2763 break;
2764 case Mips::BLELImmMacro:
2765 PseudoOpcode = Mips::BLEL;
2766 break;
2767 case Mips::BGELImmMacro:
2768 PseudoOpcode = Mips::BGEL;
2769 break;
2770 case Mips::BGTLImmMacro:
2771 PseudoOpcode = Mips::BGTL;
2772 break;
2773 case Mips::BLTULImmMacro:
2774 PseudoOpcode = Mips::BLTUL;
2775 break;
2776 case Mips::BLEULImmMacro:
2777 PseudoOpcode = Mips::BLEUL;
2778 break;
2779 case Mips::BGEULImmMacro:
2780 PseudoOpcode = Mips::BGEUL;
2781 break;
2782 case Mips::BGTULImmMacro:
2783 PseudoOpcode = Mips::BGTUL;
2784 break;
2785 }
2786
2787 if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
2788 false, IDLoc, Instructions))
2789 return true;
2790 }
2791
Toma Tabacu1a108322015-06-17 13:20:24 +00002792 switch (PseudoOpcode) {
2793 case Mips::BLT:
2794 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002795 case Mips::BLTL:
2796 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002797 AcceptsEquality = false;
2798 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002799 IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
2800 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002801 ZeroSrcOpcode = Mips::BGTZ;
2802 ZeroTrgOpcode = Mips::BLTZ;
2803 break;
2804 case Mips::BLE:
2805 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002806 case Mips::BLEL:
2807 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002808 AcceptsEquality = true;
2809 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002810 IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
2811 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002812 ZeroSrcOpcode = Mips::BGEZ;
2813 ZeroTrgOpcode = Mips::BLEZ;
2814 break;
2815 case Mips::BGE:
2816 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002817 case Mips::BGEL:
2818 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002819 AcceptsEquality = true;
2820 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002821 IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
2822 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002823 ZeroSrcOpcode = Mips::BLEZ;
2824 ZeroTrgOpcode = Mips::BGEZ;
2825 break;
2826 case Mips::BGT:
2827 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002828 case Mips::BGTL:
2829 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002830 AcceptsEquality = false;
2831 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002832 IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
2833 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002834 ZeroSrcOpcode = Mips::BLTZ;
2835 ZeroTrgOpcode = Mips::BGTZ;
2836 break;
2837 default:
2838 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2839 }
2840
Toma Tabacu1a108322015-06-17 13:20:24 +00002841 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
2842 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
2843 if (IsSrcRegZero && IsTrgRegZero) {
2844 // FIXME: All of these Opcode-specific if's are needed for compatibility
2845 // with GAS' behaviour. However, they may not generate the most efficient
2846 // code in some circumstances.
2847 if (PseudoOpcode == Mips::BLT) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002848 emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2849 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002850 return false;
2851 }
2852 if (PseudoOpcode == Mips::BLE) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002853 emitRX(Mips::BLEZ, 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::BGE) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002859 emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2860 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002861 Warning(IDLoc, "branch is always taken");
2862 return false;
2863 }
2864 if (PseudoOpcode == Mips::BGT) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002865 emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2866 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002867 return false;
2868 }
2869 if (PseudoOpcode == Mips::BGTU) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002870 emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
2871 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002872 return false;
2873 }
2874 if (AcceptsEquality) {
2875 // If both registers are $0 and the pseudo-branch accepts equality, it
2876 // will always be taken, so we emit an unconditional branch.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002877 emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
2878 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002879 Warning(IDLoc, "branch is always taken");
2880 return false;
2881 }
2882 // If both registers are $0 and the pseudo-branch does not accept
2883 // equality, it will never be taken, so we don't have to emit anything.
2884 return false;
2885 }
2886 if (IsSrcRegZero || IsTrgRegZero) {
2887 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
2888 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
2889 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
2890 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
2891 // the pseudo-branch will never be taken, so we don't emit anything.
2892 // This only applies to unsigned pseudo-branches.
2893 return false;
2894 }
2895 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
2896 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
2897 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
2898 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
2899 // the pseudo-branch will always be taken, so we emit an unconditional
2900 // branch.
2901 // This only applies to unsigned pseudo-branches.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002902 emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
2903 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002904 Warning(IDLoc, "branch is always taken");
2905 return false;
2906 }
2907 if (IsUnsigned) {
2908 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
2909 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
2910 // the pseudo-branch will be taken only when the non-zero register is
2911 // different from 0, so we emit a BNEZ.
2912 //
2913 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
2914 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
2915 // the pseudo-branch will be taken only when the non-zero register is
2916 // equal to 0, so we emit a BEQZ.
2917 //
2918 // Because only BLEU and BGEU branch on equality, we can use the
2919 // AcceptsEquality variable to decide when to emit the BEQZ.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002920 emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
2921 IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
2922 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002923 return false;
2924 }
2925 // If we have a signed pseudo-branch and one of the registers is $0,
2926 // we can use an appropriate compare-to-zero branch. We select which one
2927 // to use in the switch statement above.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002928 emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
2929 IsSrcRegZero ? TrgReg : SrcReg, MCOperand::createExpr(OffsetExpr),
2930 IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002931 return false;
2932 }
2933
2934 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
2935 // expansions. If it is not available, we return.
2936 unsigned ATRegNum = getATReg(IDLoc);
2937 if (!ATRegNum)
2938 return true;
2939
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002940 if (!EmittedNoMacroWarning)
2941 warnIfNoMacro(IDLoc);
Toma Tabacu1a108322015-06-17 13:20:24 +00002942
2943 // SLT fits well with 2 of our 4 pseudo-branches:
2944 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
2945 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
2946 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
2947 // This is accomplished by using a BNEZ with the result of the SLT.
2948 //
2949 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
2950 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
2951 // Because only BGE and BLE branch on equality, we can use the
2952 // AcceptsEquality variable to decide when to emit the BEQZ.
2953 // Note that the order of the SLT arguments doesn't change between
2954 // opposites.
2955 //
2956 // The same applies to the unsigned variants, except that SLTu is used
2957 // instead of SLT.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002958 emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
2959 ReverseOrderSLT ? TrgReg : SrcReg, ReverseOrderSLT ? SrcReg : TrgReg,
2960 IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002961
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002962 emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
2963 : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
2964 ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2965 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002966 return false;
2967}
2968
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002969bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc,
2970 SmallVectorImpl<MCInst> &Instructions,
2971 const bool IsMips64, const bool Signed) {
2972 if (hasMips32r6()) {
2973 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
2974 return false;
2975 }
2976
2977 warnIfNoMacro(IDLoc);
2978
2979 const MCOperand &RsRegOp = Inst.getOperand(0);
2980 assert(RsRegOp.isReg() && "expected register operand kind");
2981 unsigned RsReg = RsRegOp.getReg();
2982
2983 const MCOperand &RtRegOp = Inst.getOperand(1);
2984 assert(RtRegOp.isReg() && "expected register operand kind");
2985 unsigned RtReg = RtRegOp.getReg();
2986 unsigned DivOp;
2987 unsigned ZeroReg;
2988
2989 if (IsMips64) {
2990 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
2991 ZeroReg = Mips::ZERO_64;
2992 } else {
2993 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
2994 ZeroReg = Mips::ZERO;
2995 }
2996
2997 bool UseTraps = useTraps();
2998
2999 if (RsReg == Mips::ZERO || RsReg == Mips::ZERO_64) {
3000 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)
3001 Warning(IDLoc, "dividing zero by zero");
3002 if (IsMips64) {
3003 if (Signed && (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)) {
3004 if (UseTraps) {
3005 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
3006 return false;
3007 }
3008
3009 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
3010 return false;
3011 }
3012 } else {
3013 emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
3014 return false;
3015 }
3016 }
3017
3018 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
3019 Warning(IDLoc, "division by zero");
3020 if (Signed) {
3021 if (UseTraps) {
3022 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
3023 return false;
3024 }
3025
3026 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
3027 return false;
3028 }
3029 }
3030
3031 // FIXME: The values for these two BranchTarget variables may be different in
3032 // micromips. These magic numbers need to be removed.
3033 unsigned BranchTargetNoTraps;
3034 unsigned BranchTarget;
3035
3036 if (UseTraps) {
3037 BranchTarget = IsMips64 ? 12 : 8;
3038 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
3039 } else {
3040 BranchTarget = IsMips64 ? 20 : 16;
3041 BranchTargetNoTraps = 8;
3042 // Branch to the li instruction.
3043 emitRRI(Mips::BNE, RtReg, ZeroReg, BranchTargetNoTraps, IDLoc,
3044 Instructions);
3045 }
3046
3047 emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
3048
3049 if (!UseTraps)
3050 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
3051
3052 if (!Signed) {
3053 emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
3054 return false;
3055 }
3056
3057 unsigned ATReg = getATReg(IDLoc);
3058 if (!ATReg)
3059 return true;
3060
3061 emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, Instructions);
3062 if (IsMips64) {
3063 // Branch to the mflo instruction.
3064 emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
3065 emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, Instructions);
3066 emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, Instructions);
3067 } else {
3068 // Branch to the mflo instruction.
3069 emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
3070 emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, Instructions);
3071 }
3072
3073 if (UseTraps)
3074 emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, Instructions);
3075 else {
3076 // Branch to the mflo instruction.
3077 emitRRI(Mips::BNE, RsReg, ATReg, BranchTargetNoTraps, IDLoc, Instructions);
3078 emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, Instructions);
3079 emitII(Mips::BREAK, 0x6, 0, IDLoc, Instructions);
3080 }
3081 emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
3082 return false;
3083}
3084
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003085bool MipsAsmParser::expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU,
3086 SMLoc IDLoc,
3087 SmallVectorImpl<MCInst> &Instructions) {
3088
3089 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
3090 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() &&
3091 Inst.getOperand(2).isReg() && "Invalid instruction operand.");
3092
3093 unsigned FirstReg = Inst.getOperand(0).getReg();
3094 unsigned SecondReg = Inst.getOperand(1).getReg();
3095 unsigned ThirdReg = Inst.getOperand(2).getReg();
3096
3097 if (hasMips1() && !hasMips2()) {
3098 unsigned ATReg = getATReg(IDLoc);
3099 if (!ATReg)
3100 return true;
3101 emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, Instructions);
3102 emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, Instructions);
3103 createNop(false, IDLoc, Instructions);
3104 emitRRI(Mips::ORi, ATReg, ThirdReg, 0x3, IDLoc, Instructions);
3105 emitRRI(Mips::XORi, ATReg, ATReg, 0x2, IDLoc, Instructions);
3106 emitRR(Mips::CTC1, Mips::RA, ATReg, IDLoc, Instructions);
3107 createNop(false, IDLoc, Instructions);
3108 emitRR(IsDouble ? (Is64FPU ? Mips::CVT_W_D64 : Mips::CVT_W_D32)
3109 : Mips::CVT_W_S,
3110 FirstReg, SecondReg, IDLoc, Instructions);
3111 emitRR(Mips::CTC1, Mips::RA, ThirdReg, IDLoc, Instructions);
3112 createNop(false, IDLoc, Instructions);
3113 return false;
3114 }
3115
3116 emitRR(IsDouble ? (Is64FPU ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32)
3117 : Mips::TRUNC_W_S,
3118 FirstReg, SecondReg, IDLoc, Instructions);
3119
3120 return false;
3121}
3122
Daniel Sanders6394ee52015-10-15 14:52:58 +00003123bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
3124 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacud88d79c2015-06-23 14:39:42 +00003125 if (hasMips32r6() || hasMips64r6()) {
3126 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3127 return false;
3128 }
3129
3130 warnIfNoMacro(IDLoc);
3131
3132 const MCOperand &DstRegOp = Inst.getOperand(0);
3133 assert(DstRegOp.isReg() && "expected register operand kind");
3134
3135 const MCOperand &SrcRegOp = Inst.getOperand(1);
3136 assert(SrcRegOp.isReg() && "expected register operand kind");
3137
3138 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3139 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3140
3141 unsigned DstReg = DstRegOp.getReg();
3142 unsigned SrcReg = SrcRegOp.getReg();
3143 int64_t OffsetValue = OffsetImmOp.getImm();
3144
3145 // NOTE: We always need AT for ULHU, as it is always used as the source
3146 // register for one of the LBu's.
3147 unsigned ATReg = getATReg(IDLoc);
3148 if (!ATReg)
3149 return true;
3150
3151 // When the value of offset+1 does not fit in 16 bits, we have to load the
3152 // offset in AT, (D)ADDu the original source register (if there was one), and
3153 // then use AT as the source register for the 2 generated LBu's.
3154 bool LoadedOffsetInAT = false;
3155 if (!isInt<16>(OffsetValue + 1) || !isInt<16>(OffsetValue)) {
3156 LoadedOffsetInAT = true;
3157
3158 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003159 true, IDLoc, Instructions))
Toma Tabacud88d79c2015-06-23 14:39:42 +00003160 return true;
3161
3162 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3163 // because it will make our output more similar to GAS'. For example,
3164 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3165 // instead of just an "ori $1, $9, 32768".
3166 // NOTE: If there is no source register specified in the ULHU, the parser
3167 // will interpret it as $0.
3168 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
3169 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
3170 }
3171
3172 unsigned FirstLbuDstReg = LoadedOffsetInAT ? DstReg : ATReg;
3173 unsigned SecondLbuDstReg = LoadedOffsetInAT ? ATReg : DstReg;
3174 unsigned LbuSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3175
3176 int64_t FirstLbuOffset = 0, SecondLbuOffset = 0;
3177 if (isLittle()) {
3178 FirstLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3179 SecondLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3180 } else {
3181 FirstLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3182 SecondLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3183 }
3184
3185 unsigned SllReg = LoadedOffsetInAT ? DstReg : ATReg;
3186
Daniel Sanders6394ee52015-10-15 14:52:58 +00003187 emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
3188 FirstLbuOffset, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003189
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003190 emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondLbuOffset, IDLoc,
3191 Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003192
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003193 emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003194
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003195 emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003196
3197 return false;
3198}
3199
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003200bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc,
3201 SmallVectorImpl<MCInst> &Instructions) {
3202 if (hasMips32r6() || hasMips64r6()) {
3203 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3204 return false;
3205 }
3206
3207 const MCOperand &DstRegOp = Inst.getOperand(0);
3208 assert(DstRegOp.isReg() && "expected register operand kind");
3209
3210 const MCOperand &SrcRegOp = Inst.getOperand(1);
3211 assert(SrcRegOp.isReg() && "expected register operand kind");
3212
3213 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3214 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3215
3216 unsigned SrcReg = SrcRegOp.getReg();
3217 int64_t OffsetValue = OffsetImmOp.getImm();
3218 unsigned ATReg = 0;
3219
3220 // When the value of offset+3 does not fit in 16 bits, we have to load the
3221 // offset in AT, (D)ADDu the original source register (if there was one), and
3222 // then use AT as the source register for the generated LWL and LWR.
3223 bool LoadedOffsetInAT = false;
3224 if (!isInt<16>(OffsetValue + 3) || !isInt<16>(OffsetValue)) {
3225 ATReg = getATReg(IDLoc);
3226 if (!ATReg)
3227 return true;
3228 LoadedOffsetInAT = true;
3229
3230 warnIfNoMacro(IDLoc);
3231
3232 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003233 true, IDLoc, Instructions))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003234 return true;
3235
3236 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3237 // because it will make our output more similar to GAS'. For example,
3238 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3239 // instead of just an "ori $1, $9, 32768".
3240 // NOTE: If there is no source register specified in the ULW, the parser
3241 // will interpret it as $0.
3242 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
3243 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
3244 }
3245
3246 unsigned FinalSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3247 int64_t LeftLoadOffset = 0, RightLoadOffset = 0;
3248 if (isLittle()) {
3249 LeftLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3250 RightLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3251 } else {
3252 LeftLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3253 RightLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3254 }
3255
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003256 emitRRI(Mips::LWL, DstRegOp.getReg(), FinalSrcReg, LeftLoadOffset, IDLoc,
3257 Instructions);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003258
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003259 emitRRI(Mips::LWR, DstRegOp.getReg(), FinalSrcReg, RightLoadOffset, IDLoc,
3260 Instructions);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003261
3262 return false;
3263}
3264
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003265bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
3266 SmallVectorImpl<MCInst> &Instructions) {
3267
3268 assert (Inst.getNumOperands() == 3 && "Invalid operand count");
3269 assert (Inst.getOperand(0).isReg() &&
3270 Inst.getOperand(1).isReg() &&
3271 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
3272
3273 unsigned ATReg = Mips::NoRegister;
3274 unsigned FinalDstReg = Mips::NoRegister;
3275 unsigned DstReg = Inst.getOperand(0).getReg();
3276 unsigned SrcReg = Inst.getOperand(1).getReg();
3277 int64_t ImmValue = Inst.getOperand(2).getImm();
3278
3279 bool Is32Bit = isInt<32>(ImmValue) || isUInt<32>(ImmValue);
3280
3281 unsigned FinalOpcode = Inst.getOpcode();
3282
3283 if (DstReg == SrcReg) {
3284 ATReg = getATReg(Inst.getLoc());
3285 if (!ATReg)
3286 return true;
3287 FinalDstReg = DstReg;
3288 DstReg = ATReg;
3289 }
3290
3291 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Instructions)) {
3292 switch (FinalOpcode) {
3293 default:
3294 llvm_unreachable("unimplemented expansion");
3295 case (Mips::ADDi):
3296 FinalOpcode = Mips::ADD;
3297 break;
3298 case (Mips::ADDiu):
3299 FinalOpcode = Mips::ADDu;
3300 break;
3301 case (Mips::ANDi):
3302 FinalOpcode = Mips::AND;
3303 break;
3304 case (Mips::NORImm):
3305 FinalOpcode = Mips::NOR;
3306 break;
3307 case (Mips::ORi):
3308 FinalOpcode = Mips::OR;
3309 break;
3310 case (Mips::SLTi):
3311 FinalOpcode = Mips::SLT;
3312 break;
3313 case (Mips::SLTiu):
3314 FinalOpcode = Mips::SLTu;
3315 break;
3316 case (Mips::XORi):
3317 FinalOpcode = Mips::XOR;
3318 break;
3319 }
3320
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003321 if (FinalDstReg == Mips::NoRegister)
3322 emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, Instructions);
3323 else
3324 emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc,
3325 Instructions);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003326 return false;
3327 }
3328 return true;
3329}
3330
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003331bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc,
3332 SmallVectorImpl<MCInst> &Instructions) {
3333 unsigned ATReg = Mips::NoRegister;
3334 unsigned DReg = Inst.getOperand(0).getReg();
3335 unsigned SReg = Inst.getOperand(1).getReg();
3336 unsigned TReg = Inst.getOperand(2).getReg();
3337 unsigned TmpReg = DReg;
3338
3339 unsigned FirstShift = Mips::NOP;
3340 unsigned SecondShift = Mips::NOP;
3341
3342 if (hasMips32r2()) {
3343
3344 if (DReg == SReg) {
3345 TmpReg = getATReg(Inst.getLoc());
3346 if (!TmpReg)
3347 return true;
3348 }
3349
3350 if (Inst.getOpcode() == Mips::ROL) {
3351 emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions);
3352 emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), Instructions);
3353 return false;
3354 }
3355
3356 if (Inst.getOpcode() == Mips::ROR) {
3357 emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), Instructions);
3358 return false;
3359 }
3360
3361 return true;
3362 }
3363
3364 if (hasMips32()) {
3365
3366 switch (Inst.getOpcode()) {
3367 default:
3368 llvm_unreachable("unexpected instruction opcode");
3369 case Mips::ROL:
3370 FirstShift = Mips::SRLV;
3371 SecondShift = Mips::SLLV;
3372 break;
3373 case Mips::ROR:
3374 FirstShift = Mips::SLLV;
3375 SecondShift = Mips::SRLV;
3376 break;
3377 }
3378
3379 ATReg = getATReg(Inst.getLoc());
3380 if (!ATReg)
3381 return true;
3382
3383 emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions);
3384 emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), Instructions);
3385 emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), Instructions);
3386 emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions);
3387
3388 return false;
3389 }
3390
3391 return true;
3392}
3393
3394bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
3395 SmallVectorImpl<MCInst> &Instructions) {
3396
3397 unsigned ATReg = Mips::NoRegister;
3398 unsigned DReg = Inst.getOperand(0).getReg();
3399 unsigned SReg = Inst.getOperand(1).getReg();
3400 int64_t ImmValue = Inst.getOperand(2).getImm();
3401
3402 unsigned FirstShift = Mips::NOP;
3403 unsigned SecondShift = Mips::NOP;
3404
3405 if (hasMips32r2()) {
3406
3407 if (Inst.getOpcode() == Mips::ROLImm) {
3408 uint64_t MaxShift = 32;
3409 uint64_t ShiftValue = ImmValue;
3410 if (ImmValue != 0)
3411 ShiftValue = MaxShift - ImmValue;
3412 emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), Instructions);
3413 return false;
3414 }
3415
3416 if (Inst.getOpcode() == Mips::RORImm) {
3417 emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), Instructions);
3418 return false;
3419 }
3420
3421 return true;
3422 }
3423
3424 if (hasMips32()) {
3425
3426 if (ImmValue == 0) {
3427 emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), Instructions);
3428 return false;
3429 }
3430
3431 switch (Inst.getOpcode()) {
3432 default:
3433 llvm_unreachable("unexpected instruction opcode");
3434 case Mips::ROLImm:
3435 FirstShift = Mips::SLL;
3436 SecondShift = Mips::SRL;
3437 break;
3438 case Mips::RORImm:
3439 FirstShift = Mips::SRL;
3440 SecondShift = Mips::SLL;
3441 break;
3442 }
3443
3444 ATReg = getATReg(Inst.getLoc());
3445 if (!ATReg)
3446 return true;
3447
3448 emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), Instructions);
3449 emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), Instructions);
3450 emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions);
3451
3452 return false;
3453 }
3454
3455 return true;
3456}
3457
3458bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc,
3459 SmallVectorImpl<MCInst> &Instructions) {
3460
3461 unsigned ATReg = Mips::NoRegister;
3462 unsigned DReg = Inst.getOperand(0).getReg();
3463 unsigned SReg = Inst.getOperand(1).getReg();
3464 unsigned TReg = Inst.getOperand(2).getReg();
3465 unsigned TmpReg = DReg;
3466
3467 unsigned FirstShift = Mips::NOP;
3468 unsigned SecondShift = Mips::NOP;
3469
3470 if (hasMips64r2()) {
3471
3472 if (TmpReg == SReg) {
3473 TmpReg = getATReg(Inst.getLoc());
3474 if (!TmpReg)
3475 return true;
3476 }
3477
3478 if (Inst.getOpcode() == Mips::DROL) {
3479 emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions);
3480 emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), Instructions);
3481 return false;
3482 }
3483
3484 if (Inst.getOpcode() == Mips::DROR) {
3485 emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), Instructions);
3486 return false;
3487 }
3488
3489 return true;
3490 }
3491
3492 if (hasMips64()) {
3493
3494 switch (Inst.getOpcode()) {
3495 default:
3496 llvm_unreachable("unexpected instruction opcode");
3497 case Mips::DROL:
3498 FirstShift = Mips::DSRLV;
3499 SecondShift = Mips::DSLLV;
3500 break;
3501 case Mips::DROR:
3502 FirstShift = Mips::DSLLV;
3503 SecondShift = Mips::DSRLV;
3504 break;
3505 }
3506
3507 ATReg = getATReg(Inst.getLoc());
3508 if (!ATReg)
3509 return true;
3510
3511 emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions);
3512 emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), Instructions);
3513 emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), Instructions);
3514 emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions);
3515
3516 return false;
3517 }
3518
3519 return true;
3520}
3521
3522bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
3523 SmallVectorImpl<MCInst> &Instructions) {
3524
3525 unsigned ATReg = Mips::NoRegister;
3526 unsigned DReg = Inst.getOperand(0).getReg();
3527 unsigned SReg = Inst.getOperand(1).getReg();
3528 int64_t ImmValue = Inst.getOperand(2).getImm() % 64;
3529
3530 unsigned FirstShift = Mips::NOP;
3531 unsigned SecondShift = Mips::NOP;
3532
3533 MCInst TmpInst;
3534
3535 if (hasMips64r2()) {
3536
3537 unsigned FinalOpcode = Mips::NOP;
3538 if (ImmValue == 0)
3539 FinalOpcode = Mips::DROTR;
3540 else if (ImmValue % 32 == 0)
3541 FinalOpcode = Mips::DROTR32;
3542 else if ((ImmValue >= 1) && (ImmValue <= 32)) {
3543 if (Inst.getOpcode() == Mips::DROLImm)
3544 FinalOpcode = Mips::DROTR32;
3545 else
3546 FinalOpcode = Mips::DROTR;
3547 } else if (ImmValue >= 33) {
3548 if (Inst.getOpcode() == Mips::DROLImm)
3549 FinalOpcode = Mips::DROTR;
3550 else
3551 FinalOpcode = Mips::DROTR32;
3552 }
3553
3554 uint64_t ShiftValue = ImmValue % 32;
3555 if (Inst.getOpcode() == Mips::DROLImm)
3556 ShiftValue = (32 - ImmValue % 32) % 32;
3557
3558 emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), Instructions);
3559
3560 return false;
3561 }
3562
3563 if (hasMips64()) {
3564
3565 if (ImmValue == 0) {
3566 emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), Instructions);
3567 return false;
3568 }
3569
3570 switch (Inst.getOpcode()) {
3571 default:
3572 llvm_unreachable("unexpected instruction opcode");
3573 case Mips::DROLImm:
3574 if ((ImmValue >= 1) && (ImmValue <= 31)) {
3575 FirstShift = Mips::DSLL;
3576 SecondShift = Mips::DSRL32;
3577 }
3578 if (ImmValue == 32) {
3579 FirstShift = Mips::DSLL32;
3580 SecondShift = Mips::DSRL32;
3581 }
3582 if ((ImmValue >= 33) && (ImmValue <= 63)) {
3583 FirstShift = Mips::DSLL32;
3584 SecondShift = Mips::DSRL;
3585 }
3586 break;
3587 case Mips::DRORImm:
3588 if ((ImmValue >= 1) && (ImmValue <= 31)) {
3589 FirstShift = Mips::DSRL;
3590 SecondShift = Mips::DSLL32;
3591 }
3592 if (ImmValue == 32) {
3593 FirstShift = Mips::DSRL32;
3594 SecondShift = Mips::DSLL32;
3595 }
3596 if ((ImmValue >= 33) && (ImmValue <= 63)) {
3597 FirstShift = Mips::DSRL32;
3598 SecondShift = Mips::DSLL;
3599 }
3600 break;
3601 }
3602
3603 ATReg = getATReg(Inst.getLoc());
3604 if (!ATReg)
3605 return true;
3606
3607 emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), Instructions);
3608 emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32, Inst.getLoc(), Instructions);
3609 emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions);
3610
3611 return false;
3612 }
3613
3614 return true;
3615}
3616
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003617bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc,
3618 SmallVectorImpl<MCInst> &Instructions) {
3619
3620 unsigned FirstRegOp = Inst.getOperand(0).getReg();
3621 unsigned SecondRegOp = Inst.getOperand(1).getReg();
3622
3623 emitRI(Mips::BGEZ, SecondRegOp, 8, IDLoc, Instructions);
3624 if (FirstRegOp != SecondRegOp)
3625 emitRRR(Mips::ADDu, FirstRegOp, SecondRegOp, Mips::ZERO, IDLoc, Instructions);
3626 else
3627 createNop(false, IDLoc, Instructions);
3628 emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, Instructions);
3629
3630 return false;
3631}
3632
Toma Tabacu234482a2015-03-16 12:03:39 +00003633void MipsAsmParser::createNop(bool hasShortDelaySlot, SMLoc IDLoc,
3634 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003635 if (hasShortDelaySlot)
3636 emitRR(Mips::MOVE16_MM, Mips::ZERO, Mips::ZERO, IDLoc, Instructions);
3637 else
3638 emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, Instructions);
Toma Tabacu234482a2015-03-16 12:03:39 +00003639}
3640
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003641void MipsAsmParser::createAddu(unsigned DstReg, unsigned SrcReg,
Toma Tabacu0b3e9782015-06-23 14:00:54 +00003642 unsigned TrgReg, bool Is64Bit,
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003643 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanders03f9c012015-07-14 12:24:22 +00003644 emitRRR(Is64Bit ? Mips::DADDu : Mips::ADDu, DstReg, SrcReg, TrgReg, SMLoc(),
3645 Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003646}
3647
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003648void MipsAsmParser::createCpRestoreMemOp(
3649 bool IsLoad, int StackOffset, SMLoc IDLoc,
3650 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003651 // If the offset can not fit into 16 bits, we need to expand.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003652 if (!isInt<16>(StackOffset)) {
3653 MCInst MemInst;
3654 MemInst.setOpcode(IsLoad ? Mips::LW : Mips::SW);
3655 MemInst.addOperand(MCOperand::createReg(Mips::GP));
3656 MemInst.addOperand(MCOperand::createReg(Mips::SP));
3657 MemInst.addOperand(MCOperand::createImm(StackOffset));
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003658 expandMemInst(MemInst, IDLoc, Instructions, IsLoad, true /*HasImmOpnd*/);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003659 return;
3660 }
3661
3662 emitRRI(IsLoad ? Mips::LW : Mips::SW, Mips::GP, Mips::SP, StackOffset, IDLoc,
3663 Instructions);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003664}
3665
Matheus Almeida595fcab2014-06-11 15:05:56 +00003666unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
3667 // As described by the Mips32r2 spec, the registers Rd and Rs for
3668 // jalr.hb must be different.
3669 unsigned Opcode = Inst.getOpcode();
3670
3671 if (Opcode == Mips::JALR_HB &&
3672 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
3673 return Match_RequiresDifferentSrcAndDst;
3674
3675 return Match_Success;
3676}
3677
Daniel Sanders52da7af2015-11-06 12:11:03 +00003678static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
3679 uint64_t ErrorInfo) {
3680 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
3681 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
3682 if (ErrorLoc == SMLoc())
3683 return Loc;
3684 return ErrorLoc;
3685 }
3686 return Loc;
3687}
3688
David Blaikie960ea3f2014-06-08 16:18:35 +00003689bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3690 OperandVector &Operands,
3691 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003692 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00003693 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00003694
Jack Carterb4dbc172012-09-05 23:34:03 +00003695 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00003696 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00003697 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003698 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00003699
3700 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003701 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003702 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00003703 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00003704 for (unsigned i = 0; i < Instructions.size(); i++)
Akira Hatanakabd9fc282015-11-14 05:20:05 +00003705 Out.EmitInstruction(Instructions[i], getSTI());
Jack Carterb4dbc172012-09-05 23:34:03 +00003706 return false;
3707 }
3708 case Match_MissingFeature:
3709 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
3710 return true;
3711 case Match_InvalidOperand: {
3712 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00003713 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003714 if (ErrorInfo >= Operands.size())
3715 return Error(IDLoc, "too few operands for instruction");
3716
Daniel Sanders52da7af2015-11-06 12:11:03 +00003717 ErrorLoc = Operands[ErrorInfo]->getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00003718 if (ErrorLoc == SMLoc())
3719 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00003720 }
3721
3722 return Error(ErrorLoc, "invalid operand for instruction");
3723 }
3724 case Match_MnemonicFail:
3725 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00003726 case Match_RequiresDifferentSrcAndDst:
3727 return Error(IDLoc, "source and destination must be different");
Daniel Sanders52da7af2015-11-06 12:11:03 +00003728 case Match_Immz:
3729 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00003730 case Match_UImm1_0:
3731 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3732 "expected 1-bit unsigned immediate");
Daniel Sandersea4f6532015-11-06 12:22:31 +00003733 case Match_UImm2_0:
3734 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3735 "expected 2-bit unsigned immediate");
3736 case Match_UImm2_1:
3737 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3738 "expected immediate in range 1 .. 4");
Daniel Sanders38ce0f62015-11-06 12:31:27 +00003739 case Match_UImm3_0:
3740 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3741 "expected 3-bit unsigned immediate");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00003742 case Match_UImm4_0:
3743 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3744 "expected 4-bit unsigned immediate");
Daniel Sanders78e89022016-03-11 11:37:50 +00003745 case Match_SImm4_0:
3746 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3747 "expected 4-bit signed immediate");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00003748 case Match_UImm5_0:
3749 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3750 "expected 5-bit unsigned immediate");
Daniel Sanders0f17d0d2016-03-22 14:29:53 +00003751 case Match_SImm5_0:
3752 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3753 "expected 5-bit signed immediate");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00003754 case Match_UImm5_1:
3755 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3756 "expected immediate in range 1 .. 32");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00003757 case Match_UImm5_32:
3758 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3759 "expected immediate in range 32 .. 63");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00003760 case Match_UImm5_33:
3761 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3762 "expected immediate in range 33 .. 64");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00003763 case Match_UImm5_0_Report_UImm6:
3764 // This is used on UImm5 operands that have a corresponding UImm5_32
3765 // operand to avoid confusing the user.
3766 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3767 "expected 6-bit unsigned immediate");
3768 case Match_UImm5_Lsl2:
3769 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3770 "expected both 7-bit unsigned immediate and multiple of 4");
Hrvoje Varga46458d02016-02-25 12:53:29 +00003771 case Match_UImmRange2_64:
3772 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3773 "expected immediate in range 2 .. 64");
Daniel Sanders59d092f2015-12-08 13:49:19 +00003774 case Match_UImm6_0:
3775 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3776 "expected 6-bit unsigned immediate");
Daniel Sanders19b7f762016-03-14 11:16:56 +00003777 case Match_UImm6_Lsl2:
3778 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3779 "expected both 8-bit unsigned immediate and multiple of 4");
Daniel Sanders78e89022016-03-11 11:37:50 +00003780 case Match_SImm6_0:
Zlatko Buljan252cca52015-12-18 08:59:37 +00003781 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3782 "expected 6-bit signed immediate");
3783 case Match_UImm7_0:
3784 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3785 "expected 7-bit unsigned immediate");
Daniel Sanders97297772016-03-22 14:40:00 +00003786 case Match_UImm7_N1:
3787 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3788 "expected immediate in range -1 .. 126");
3789 case Match_SImm7_Lsl2:
3790 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3791 "expected both 9-bit signed immediate and multiple of 4");
Daniel Sanders106d2d42015-12-08 14:42:10 +00003792 case Match_UImm8_0:
3793 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3794 "expected 8-bit unsigned immediate");
Daniel Sanders3c722312015-12-09 13:48:05 +00003795 case Match_UImm10_0:
3796 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3797 "expected 10-bit unsigned immediate");
Daniel Sanders837f1512016-03-24 13:26:59 +00003798 case Match_SImm10_0:
3799 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3800 "expected 10-bit signed immediate");
Daniel Sanderseab31462016-03-31 14:23:20 +00003801 case Match_SImm11_0:
3802 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3803 "expected 11-bit signed immediate");
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00003804 case Match_UImm16:
3805 case Match_UImm16_Relaxed:
3806 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3807 "expected 16-bit unsigned immediate");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00003808 case Match_SImm16:
3809 case Match_SImm16_Relaxed:
3810 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3811 "expected 16-bit signed immediate");
Daniel Sanders03a8d2f2016-02-29 16:06:38 +00003812 case Match_UImm20_0:
3813 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3814 "expected 20-bit unsigned immediate");
Daniel Sanders5d3840f2016-03-29 09:40:38 +00003815 case Match_UImm26_0:
3816 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3817 "expected 26-bit unsigned immediate");
Daniel Sanders2e9f69d2016-03-31 13:15:23 +00003818 case Match_MemSImm9:
3819 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3820 "expected memory with 9-bit signed offset");
3821 case Match_MemGPSImm9:
3822 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3823 "expected memory with $gp and 9-bit signed offset");
Daniel Sandersdc0602a2016-03-31 14:12:01 +00003824 case Match_MemSImm10:
3825 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3826 "expected memory with 10-bit signed offset");
3827 case Match_MemSImm10Lsl1:
3828 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3829 "expected memory with 11-bit signed offset and multiple of 2");
3830 case Match_MemSImm10Lsl2:
3831 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3832 "expected memory with 12-bit signed offset and multiple of 4");
3833 case Match_MemSImm10Lsl3:
3834 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3835 "expected memory with 13-bit signed offset and multiple of 8");
Daniel Sanderseab31462016-03-31 14:23:20 +00003836 case Match_MemSImm11:
3837 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3838 "expected memory with 11-bit signed offset");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00003839 case Match_MemSImm16:
3840 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3841 "expected memory with 16-bit signed offset");
Jack Carterb4dbc172012-09-05 23:34:03 +00003842 }
Craig Topper589ceee2015-01-03 08:16:34 +00003843
3844 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00003845}
3846
Toma Tabacud9d344b2015-04-27 14:05:04 +00003847void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
3848 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
3849 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
3850 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003851}
3852
Toma Tabacu81496c12015-05-20 08:54:45 +00003853void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
3854 if (!AssemblerOptions.back()->isMacro())
3855 Warning(Loc, "macro instruction expanded into multiple instructions");
3856}
3857
Daniel Sandersef638fe2014-10-03 15:37:37 +00003858void
3859MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
3860 SMRange Range, bool ShowColors) {
3861 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00003862 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00003863 ShowColors);
3864}
3865
Jack Carter1ac53222013-02-20 23:11:17 +00003866int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003867 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003868
Vladimir Medic4c299852013-11-06 11:27:05 +00003869 CC = StringSwitch<unsigned>(Name)
3870 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003871 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00003872 .Case("a0", 4)
3873 .Case("a1", 5)
3874 .Case("a2", 6)
3875 .Case("a3", 7)
3876 .Case("v0", 2)
3877 .Case("v1", 3)
3878 .Case("s0", 16)
3879 .Case("s1", 17)
3880 .Case("s2", 18)
3881 .Case("s3", 19)
3882 .Case("s4", 20)
3883 .Case("s5", 21)
3884 .Case("s6", 22)
3885 .Case("s7", 23)
3886 .Case("k0", 26)
3887 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003888 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00003889 .Case("sp", 29)
3890 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003891 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00003892 .Case("ra", 31)
3893 .Case("t0", 8)
3894 .Case("t1", 9)
3895 .Case("t2", 10)
3896 .Case("t3", 11)
3897 .Case("t4", 12)
3898 .Case("t5", 13)
3899 .Case("t6", 14)
3900 .Case("t7", 15)
3901 .Case("t8", 24)
3902 .Case("t9", 25)
3903 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003904
Toma Tabacufda445c2014-09-15 15:33:01 +00003905 if (!(isABI_N32() || isABI_N64()))
3906 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003907
Daniel Sandersef638fe2014-10-03 15:37:37 +00003908 if (12 <= CC && CC <= 15) {
3909 // Name is one of t4-t7
3910 AsmToken RegTok = getLexer().peekTok();
3911 SMRange RegRange = RegTok.getLocRange();
3912
3913 StringRef FixedName = StringSwitch<StringRef>(Name)
3914 .Case("t4", "t0")
3915 .Case("t5", "t1")
3916 .Case("t6", "t2")
3917 .Case("t7", "t3")
3918 .Default("");
3919 assert(FixedName != "" && "Register name is not one of t4-t7.");
3920
3921 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
3922 "Did you mean $" + FixedName + "?", RegRange);
3923 }
3924
Toma Tabacufda445c2014-09-15 15:33:01 +00003925 // Although SGI documentation just cuts out t0-t3 for n32/n64,
3926 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
3927 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
3928 if (8 <= CC && CC <= 11)
3929 CC += 4;
3930
3931 if (CC == -1)
3932 CC = StringSwitch<unsigned>(Name)
3933 .Case("a4", 8)
3934 .Case("a5", 9)
3935 .Case("a6", 10)
3936 .Case("a7", 11)
3937 .Case("kt0", 26)
3938 .Case("kt1", 27)
3939 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003940
3941 return CC;
3942}
Jack Carterd0bd6422013-04-18 00:41:53 +00003943
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003944int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
3945 int CC;
3946
3947 CC = StringSwitch<unsigned>(Name)
3948 .Case("hwr_cpunum", 0)
3949 .Case("hwr_synci_step", 1)
3950 .Case("hwr_cc", 2)
3951 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00003952 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003953 .Default(-1);
3954
3955 return CC;
3956}
3957
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003958int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003959
Jack Cartera63b16a2012-09-07 00:23:42 +00003960 if (Name[0] == 'f') {
3961 StringRef NumString = Name.substr(1);
3962 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003963 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003964 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003965 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00003966 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003967 return IntVal;
3968 }
3969 return -1;
3970}
Jack Cartera63b16a2012-09-07 00:23:42 +00003971
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003972int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
3973
3974 if (Name.startswith("fcc")) {
3975 StringRef NumString = Name.substr(3);
3976 unsigned IntVal;
3977 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003978 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003979 if (IntVal > 7) // There are only 8 fcc registers.
3980 return -1;
3981 return IntVal;
3982 }
3983 return -1;
3984}
3985
3986int MipsAsmParser::matchACRegisterName(StringRef Name) {
3987
Akira Hatanaka274d24c2013-08-14 01:15:52 +00003988 if (Name.startswith("ac")) {
3989 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003990 unsigned IntVal;
3991 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003992 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003993 if (IntVal > 3) // There are only 3 acc registers.
3994 return -1;
3995 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00003996 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003997 return -1;
3998}
Jack Carterd0bd6422013-04-18 00:41:53 +00003999
Jack Carter5dc8ac92013-09-25 23:50:44 +00004000int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
4001 unsigned IntVal;
4002
4003 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
4004 return -1;
4005
4006 if (IntVal > 31)
4007 return -1;
4008
4009 return IntVal;
4010}
4011
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00004012int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
4013 int CC;
4014
4015 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00004016 .Case("msair", 0)
4017 .Case("msacsr", 1)
4018 .Case("msaaccess", 2)
4019 .Case("msasave", 3)
4020 .Case("msamodify", 4)
4021 .Case("msarequest", 5)
4022 .Case("msamap", 6)
4023 .Case("msaunmap", 7)
4024 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00004025
4026 return CC;
4027}
4028
Toma Tabacu89a712b2015-04-15 10:48:56 +00004029unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00004030 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00004031 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00004032 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00004033 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00004034 return 0;
4035 }
4036 unsigned AT = getReg(
4037 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00004038 return AT;
4039}
Jack Carter0b744b32012-10-04 02:29:46 +00004040
Jack Carterd0bd6422013-04-18 00:41:53 +00004041unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00004042 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00004043}
4044
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004045unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004046 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00004047 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004048}
4049
Jack Carter873c7242013-01-12 01:03:14 +00004050int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004051 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00004052 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00004053 return -1;
4054
Jack Carter873c7242013-01-12 01:03:14 +00004055 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00004056}
4057
Toma Tabacu13964452014-09-04 13:23:44 +00004058bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004059 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004060 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004061
Jack Carter30a59822012-10-04 04:03:53 +00004062 // Check if the current operand has a custom associated parser, if so, try to
4063 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00004064 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4065 if (ResTy == MatchOperand_Success)
4066 return false;
4067 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4068 // there was a match, but an error occurred, in which case, just return that
4069 // the operand parsing failed.
4070 if (ResTy == MatchOperand_ParseFail)
4071 return true;
4072
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004073 DEBUG(dbgs() << ".. Generic Parser\n");
4074
Jack Carterb4dbc172012-09-05 23:34:03 +00004075 switch (getLexer().getKind()) {
4076 default:
4077 Error(Parser.getTok().getLoc(), "unexpected token in operand");
4078 return true;
4079 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00004080 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00004081 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00004082
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004083 // Almost all registers have been parsed by custom parsers. There is only
4084 // one exception to this. $zero (and it's alias $0) will reach this point
4085 // for div, divu, and similar instructions because it is not an operand
4086 // to the instruction definition but an explicit register. Special case
4087 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00004088 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00004089 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004090
Jack Carterd0bd6422013-04-18 00:41:53 +00004091 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00004092 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004093 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00004094 return true;
4095
Jack Carter873c7242013-01-12 01:03:14 +00004096 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00004097 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00004098 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00004099 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004100 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00004101
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004102 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004103 return false;
4104 }
Vladimir Medic4c299852013-11-06 11:27:05 +00004105 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00004106 case AsmToken::LParen:
4107 case AsmToken::Minus:
4108 case AsmToken::Plus:
4109 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00004110 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00004111 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004112 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00004113 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004114 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00004115 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00004116 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00004117 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004118 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00004119 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00004120 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00004121 return true;
4122
Jack Carter873c7242013-01-12 01:03:14 +00004123 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4124
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004125 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00004126 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004127 } // case AsmToken::Percent
4128 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00004129 return true;
4130}
4131
Vladimir Medic4c299852013-11-06 11:27:05 +00004132const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00004133 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00004134 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00004135 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00004136 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00004137 // It's a constant, evaluate reloc value.
4138 int16_t Val;
4139 switch (getVariantKind(RelocStr)) {
4140 case MCSymbolRefExpr::VK_Mips_ABS_LO:
4141 // Get the 1st 16-bits.
4142 Val = MCE->getValue() & 0xffff;
4143 break;
4144 case MCSymbolRefExpr::VK_Mips_ABS_HI:
Simon Atanasyan2fc1e3b2016-02-09 22:31:49 +00004145 case MCSymbolRefExpr::VK_Mips_GOT:
Sasa Stankovic06c47802014-04-03 10:37:45 +00004146 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
4147 // 16 bits being negative.
4148 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
4149 break;
4150 case MCSymbolRefExpr::VK_Mips_HIGHER:
4151 // Get the 3rd 16-bits.
4152 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
4153 break;
4154 case MCSymbolRefExpr::VK_Mips_HIGHEST:
4155 // Get the 4th 16-bits.
4156 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
4157 break;
4158 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00004159 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00004160 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00004161 return MCConstantExpr::create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00004162 }
4163
Jack Carterb5cf5902013-04-17 00:18:04 +00004164 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004165 // It's a symbol, create a symbolic expression from the symbol.
Toma Tabacu07c97b32015-06-17 10:43:45 +00004166 const MCSymbol *Symbol = &MSRE->getSymbol();
Jack Carterb5cf5902013-04-17 00:18:04 +00004167 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004168 Res = MCSymbolRefExpr::create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004169 return Res;
4170 }
4171
4172 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00004173 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
4174
Sasa Stankovic06c47802014-04-03 10:37:45 +00004175 // Try to create target expression.
4176 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
Jim Grosbach13760bd2015-05-30 01:25:56 +00004177 return MipsMCExpr::create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00004178
Jack Carterd0bd6422013-04-18 00:41:53 +00004179 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
4180 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004181 Res = MCBinaryExpr::create(BE->getOpcode(), LExp, RExp, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004182 return Res;
4183 }
4184
4185 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004186 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004187 Res = MCUnaryExpr::create(UN->getOpcode(), UnExp, getContext());
Jack Carterd0bd6422013-04-18 00:41:53 +00004188 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00004189 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004190 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00004191 return Expr;
4192}
4193
4194bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
4195
4196 switch (Expr->getKind()) {
4197 case MCExpr::Constant:
4198 return true;
4199 case MCExpr::SymbolRef:
4200 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
4201 case MCExpr::Binary:
4202 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
4203 if (!isEvaluated(BE->getLHS()))
4204 return false;
4205 return isEvaluated(BE->getRHS());
4206 }
4207 case MCExpr::Unary:
4208 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00004209 case MCExpr::Target:
4210 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004211 }
Jack Carterb5cf5902013-04-17 00:18:04 +00004212 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00004213}
Jack Carterd0bd6422013-04-18 00:41:53 +00004214
Jack Carterb5cf5902013-04-17 00:18:04 +00004215bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004216 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00004217 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00004218 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00004219 if (Tok.isNot(AsmToken::Identifier))
4220 return true;
4221
Yaron Keren075759a2015-03-30 15:42:36 +00004222 std::string Str = Tok.getIdentifier();
Jack Carterb5cf5902013-04-17 00:18:04 +00004223
Jack Carterd0bd6422013-04-18 00:41:53 +00004224 Parser.Lex(); // Eat the identifier.
4225 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004226 const MCExpr *IdVal;
4227 SMLoc EndLoc;
4228
4229 if (getLexer().getKind() == AsmToken::LParen) {
4230 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004231 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004232 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004233 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004234 const AsmToken &nextTok = Parser.getTok();
4235 if (nextTok.isNot(AsmToken::Identifier))
4236 return true;
4237 Str += "(%";
4238 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00004239 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00004240 if (getLexer().getKind() != AsmToken::LParen)
4241 return true;
4242 } else
4243 break;
4244 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004245 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00004246 return true;
4247
4248 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00004249 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004250
4251 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00004252 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004253
Jack Carterd0bd6422013-04-18 00:41:53 +00004254 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00004255 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004256}
4257
Jack Carterb4dbc172012-09-05 23:34:03 +00004258bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
4259 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004260 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00004261 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004262 if (ResTy == MatchOperand_Success) {
4263 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00004264 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004265 StartLoc = Operand.getStartLoc();
4266 EndLoc = Operand.getEndLoc();
4267
4268 // AFAIK, we only support numeric registers and named GPR's in CFI
4269 // directives.
4270 // Don't worry about eating tokens before failing. Using an unrecognised
4271 // register is a parse error.
4272 if (Operand.isGPRAsmReg()) {
4273 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004274 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004275 }
4276
4277 return (RegNo == (unsigned)-1);
4278 }
4279
4280 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00004281 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00004282}
4283
Jack Carterb5cf5902013-04-17 00:18:04 +00004284bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004285 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00004286 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00004287 bool Result = true;
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004288 unsigned NumOfLParen = 0;
Jack Carterb5cf5902013-04-17 00:18:04 +00004289
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004290 while (getLexer().getKind() == AsmToken::LParen) {
Jack Carterb5cf5902013-04-17 00:18:04 +00004291 Parser.Lex();
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004292 ++NumOfLParen;
4293 }
Jack Carter873c7242013-01-12 01:03:14 +00004294
Jack Carterd0bd6422013-04-18 00:41:53 +00004295 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00004296 default:
4297 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00004298 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00004299 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00004300 case AsmToken::Integer:
4301 case AsmToken::Minus:
4302 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00004303 if (isParenExpr)
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004304 Result = getParser().parseParenExprOfDepth(NumOfLParen, Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00004305 else
4306 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00004307 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00004308 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004309 break;
Jack Carter873c7242013-01-12 01:03:14 +00004310 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00004311 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00004312 }
Jack Carterb5cf5902013-04-17 00:18:04 +00004313 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004314}
4315
David Blaikie960ea3f2014-06-08 16:18:35 +00004316MipsAsmParser::OperandMatchResultTy
4317MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004318 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004319 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00004320 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00004321 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00004322 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004323 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00004324 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00004325 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00004326
Jack Carterb5cf5902013-04-17 00:18:04 +00004327 if (getLexer().getKind() == AsmToken::LParen) {
4328 Parser.Lex();
4329 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004330 }
4331
Jack Carterb5cf5902013-04-17 00:18:04 +00004332 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004333 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00004334 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004335
Jack Carterd0bd6422013-04-18 00:41:53 +00004336 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004337 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004338 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00004339 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00004340 SMLoc E =
4341 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004342 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00004343 return MatchOperand_Success;
4344 }
4345 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004346 SMLoc E =
4347 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00004348
Jack Carterd0bd6422013-04-18 00:41:53 +00004349 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004350 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00004351 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004352 S, E, *this);
4353 Operands.push_back(
4354 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00004355 return MatchOperand_Success;
4356 }
4357 Error(Parser.getTok().getLoc(), "'(' expected");
4358 return MatchOperand_ParseFail;
4359 }
4360
Jack Carterd0bd6422013-04-18 00:41:53 +00004361 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004362 }
4363
Toma Tabacu13964452014-09-04 13:23:44 +00004364 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004365 if (Res != MatchOperand_Success)
4366 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004367
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004368 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00004369 Error(Parser.getTok().getLoc(), "')' expected");
4370 return MatchOperand_ParseFail;
4371 }
4372
Jack Carter873c7242013-01-12 01:03:14 +00004373 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4374
Jack Carterd0bd6422013-04-18 00:41:53 +00004375 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004376
Craig Topper062a2ba2014-04-25 05:30:21 +00004377 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004378 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00004379
Jack Carterd0bd6422013-04-18 00:41:53 +00004380 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00004381 std::unique_ptr<MipsOperand> op(
4382 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00004383 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004384 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004385 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00004386 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004387 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
4388 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004389 if (IdVal->evaluateAsAbsolute(Imm))
4390 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004391 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004392 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00004393 getContext());
4394 }
4395
David Blaikie960ea3f2014-06-08 16:18:35 +00004396 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004397 return MatchOperand_Success;
4398}
4399
David Blaikie960ea3f2014-06-08 16:18:35 +00004400bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004401 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00004402 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00004403 if (Sym) {
4404 SMLoc S = Parser.getTok().getLoc();
4405 const MCExpr *Expr;
4406 if (Sym->isVariable())
4407 Expr = Sym->getVariableValue();
4408 else
4409 return false;
4410 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004411 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00004412 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00004413 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004414 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004415 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00004416 if (ResTy == MatchOperand_Success) {
4417 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00004418 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00004419 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004420 llvm_unreachable("Should never ParseFail");
4421 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00004422 }
4423 } else if (Expr->getKind() == MCExpr::Constant) {
4424 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00004425 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00004426 Operands.push_back(
4427 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00004428 return true;
4429 }
4430 }
4431 return false;
4432}
Jack Carterd0bd6422013-04-18 00:41:53 +00004433
Jack Carter873c7242013-01-12 01:03:14 +00004434MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004435MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00004436 StringRef Identifier,
4437 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004438 int Index = matchCPURegisterName(Identifier);
4439 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004440 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004441 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4442 return MatchOperand_Success;
4443 }
4444
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004445 Index = matchHWRegsRegisterName(Identifier);
4446 if (Index != -1) {
4447 Operands.push_back(MipsOperand::createHWRegsReg(
4448 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4449 return MatchOperand_Success;
4450 }
4451
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004452 Index = matchFPURegisterName(Identifier);
4453 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004454 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004455 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4456 return MatchOperand_Success;
4457 }
4458
4459 Index = matchFCCRegisterName(Identifier);
4460 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004461 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004462 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4463 return MatchOperand_Success;
4464 }
4465
4466 Index = matchACRegisterName(Identifier);
4467 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004468 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004469 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4470 return MatchOperand_Success;
4471 }
4472
4473 Index = matchMSA128RegisterName(Identifier);
4474 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004475 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004476 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4477 return MatchOperand_Success;
4478 }
4479
4480 Index = matchMSA128CtrlRegisterName(Identifier);
4481 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004482 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004483 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4484 return MatchOperand_Success;
4485 }
4486
4487 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00004488}
4489
4490MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004491MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004492 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00004493 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004494
4495 if (Token.is(AsmToken::Identifier)) {
4496 DEBUG(dbgs() << ".. identifier\n");
4497 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00004498 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004499 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00004500 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004501 } else if (Token.is(AsmToken::Integer)) {
4502 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00004503 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004504 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
4505 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004506 return MatchOperand_Success;
4507 }
4508
4509 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
4510
4511 return MatchOperand_NoMatch;
4512}
4513
David Blaikie960ea3f2014-06-08 16:18:35 +00004514MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004515MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004516 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004517 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004518
4519 auto Token = Parser.getTok();
4520
4521 SMLoc S = Token.getLoc();
4522
4523 if (Token.isNot(AsmToken::Dollar)) {
4524 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
4525 if (Token.is(AsmToken::Identifier)) {
4526 if (searchSymbolAlias(Operands))
4527 return MatchOperand_Success;
4528 }
4529 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
4530 return MatchOperand_NoMatch;
4531 }
4532 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004533
Toma Tabacu13964452014-09-04 13:23:44 +00004534 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00004535 if (ResTy == MatchOperand_Success) {
4536 Parser.Lex(); // $
4537 Parser.Lex(); // identifier
4538 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004539 return ResTy;
4540}
4541
4542MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004543MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004544 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004545 switch (getLexer().getKind()) {
4546 default:
4547 return MatchOperand_NoMatch;
4548 case AsmToken::LParen:
4549 case AsmToken::Minus:
4550 case AsmToken::Plus:
4551 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00004552 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004553 case AsmToken::String:
4554 break;
4555 }
4556
4557 const MCExpr *IdVal;
4558 SMLoc S = Parser.getTok().getLoc();
4559 if (getParser().parseExpression(IdVal))
4560 return MatchOperand_ParseFail;
4561
4562 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4563 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
4564 return MatchOperand_Success;
4565}
4566
David Blaikie960ea3f2014-06-08 16:18:35 +00004567MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004568MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004569 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004570 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004571
4572 SMLoc S = getLexer().getLoc();
4573
4574 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00004575 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004576 if (ResTy != MatchOperand_NoMatch)
4577 return ResTy;
4578
Daniel Sanders315386c2014-04-01 10:40:14 +00004579 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00004580 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00004581 if (ResTy != MatchOperand_NoMatch)
4582 return ResTy;
4583
Daniel Sandersffd84362014-04-01 10:41:48 +00004584 const MCExpr *Expr = nullptr;
4585 if (Parser.parseExpression(Expr)) {
4586 // We have no way of knowing if a symbol was consumed so we must ParseFail
4587 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004588 }
Daniel Sandersffd84362014-04-01 10:41:48 +00004589 Operands.push_back(
4590 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004591 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00004592}
4593
Vladimir Medic2b953d02013-10-01 09:48:56 +00004594MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00004595MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004596 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00004597 const MCExpr *IdVal;
4598 // If the first token is '$' we may have register operand.
4599 if (Parser.getTok().is(AsmToken::Dollar))
4600 return MatchOperand_NoMatch;
4601 SMLoc S = Parser.getTok().getLoc();
4602 if (getParser().parseExpression(IdVal))
4603 return MatchOperand_ParseFail;
4604 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00004605 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00004606 int64_t Val = MCE->getValue();
4607 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4608 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00004609 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00004610 return MatchOperand_Success;
4611}
4612
Matheus Almeida779c5932013-11-18 12:32:49 +00004613MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004614MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004615 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00004616 switch (getLexer().getKind()) {
4617 default:
4618 return MatchOperand_NoMatch;
4619 case AsmToken::LParen:
4620 case AsmToken::Plus:
4621 case AsmToken::Minus:
4622 case AsmToken::Integer:
4623 break;
4624 }
4625
4626 const MCExpr *Expr;
4627 SMLoc S = Parser.getTok().getLoc();
4628
4629 if (getParser().parseExpression(Expr))
4630 return MatchOperand_ParseFail;
4631
4632 int64_t Val;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004633 if (!Expr->evaluateAsAbsolute(Val)) {
Matheus Almeida779c5932013-11-18 12:32:49 +00004634 Error(S, "expected immediate value");
4635 return MatchOperand_ParseFail;
4636 }
4637
4638 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
4639 // and because the CPU always adds one to the immediate field, the allowed
4640 // range becomes 1..4. We'll only check the range here and will deal
4641 // with the addition/subtraction when actually decoding/encoding
4642 // the instruction.
4643 if (Val < 1 || Val > 4) {
4644 Error(S, "immediate not in range (1..4)");
4645 return MatchOperand_ParseFail;
4646 }
4647
Jack Carter3b2c96e2014-01-22 23:31:38 +00004648 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004649 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00004650 return MatchOperand_Success;
4651}
4652
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004653MipsAsmParser::OperandMatchResultTy
4654MipsAsmParser::parseRegisterList(OperandVector &Operands) {
4655 MCAsmParser &Parser = getParser();
4656 SmallVector<unsigned, 10> Regs;
4657 unsigned RegNo;
4658 unsigned PrevReg = Mips::NoRegister;
4659 bool RegRange = false;
4660 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4661
4662 if (Parser.getTok().isNot(AsmToken::Dollar))
4663 return MatchOperand_ParseFail;
4664
4665 SMLoc S = Parser.getTok().getLoc();
4666 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
4667 SMLoc E = getLexer().getLoc();
4668 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
4669 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
4670 if (RegRange) {
4671 // Remove last register operand because registers from register range
4672 // should be inserted first.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004673 if ((isGP64bit() && RegNo == Mips::RA_64) ||
4674 (!isGP64bit() && RegNo == Mips::RA)) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004675 Regs.push_back(RegNo);
4676 } else {
4677 unsigned TmpReg = PrevReg + 1;
4678 while (TmpReg <= RegNo) {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004679 if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) ||
4680 (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) &&
4681 isGP64bit())) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004682 Error(E, "invalid register operand");
4683 return MatchOperand_ParseFail;
4684 }
4685
4686 PrevReg = TmpReg;
4687 Regs.push_back(TmpReg++);
4688 }
4689 }
4690
4691 RegRange = false;
4692 } else {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004693 if ((PrevReg == Mips::NoRegister) &&
4694 ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) ||
4695 (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA)))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004696 Error(E, "$16 or $31 expected");
4697 return MatchOperand_ParseFail;
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004698 } else if (!(((RegNo == Mips::FP || RegNo == Mips::RA ||
4699 (RegNo >= Mips::S0 && RegNo <= Mips::S7)) &&
4700 !isGP64bit()) ||
4701 ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 ||
4702 (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) &&
4703 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004704 Error(E, "invalid register operand");
4705 return MatchOperand_ParseFail;
4706 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004707 ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) ||
4708 (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 &&
4709 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004710 Error(E, "consecutive register numbers expected");
4711 return MatchOperand_ParseFail;
4712 }
4713
4714 Regs.push_back(RegNo);
4715 }
4716
4717 if (Parser.getTok().is(AsmToken::Minus))
4718 RegRange = true;
4719
4720 if (!Parser.getTok().isNot(AsmToken::Minus) &&
4721 !Parser.getTok().isNot(AsmToken::Comma)) {
4722 Error(E, "',' or '-' expected");
4723 return MatchOperand_ParseFail;
4724 }
4725
4726 Lex(); // Consume comma or minus
4727 if (Parser.getTok().isNot(AsmToken::Dollar))
4728 break;
4729
4730 PrevReg = RegNo;
4731 }
4732
4733 SMLoc E = Parser.getTok().getLoc();
4734 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4735 parseMemOperand(Operands);
4736 return MatchOperand_Success;
4737}
4738
Zoran Jovanovic2deca342014-12-16 14:59:10 +00004739MipsAsmParser::OperandMatchResultTy
4740MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
4741 MCAsmParser &Parser = getParser();
4742
4743 SMLoc S = Parser.getTok().getLoc();
4744 if (parseAnyRegister(Operands) != MatchOperand_Success)
4745 return MatchOperand_ParseFail;
4746
4747 SMLoc E = Parser.getTok().getLoc();
4748 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
4749 unsigned Reg = Op.getGPR32Reg();
4750 Operands.pop_back();
4751 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
4752 return MatchOperand_Success;
4753}
4754
Zoran Jovanovic41688672015-02-10 16:36:20 +00004755MipsAsmParser::OperandMatchResultTy
4756MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
4757 MCAsmParser &Parser = getParser();
4758 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4759 SmallVector<unsigned, 10> Regs;
4760
4761 if (Parser.getTok().isNot(AsmToken::Dollar))
4762 return MatchOperand_ParseFail;
4763
4764 SMLoc S = Parser.getTok().getLoc();
4765
4766 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4767 return MatchOperand_ParseFail;
4768
4769 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4770 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4771 Regs.push_back(RegNo);
4772
4773 SMLoc E = Parser.getTok().getLoc();
4774 if (Parser.getTok().isNot(AsmToken::Comma)) {
4775 Error(E, "',' expected");
4776 return MatchOperand_ParseFail;
4777 }
4778
4779 // Remove comma.
4780 Parser.Lex();
4781
4782 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4783 return MatchOperand_ParseFail;
4784
4785 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4786 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4787 Regs.push_back(RegNo);
4788
4789 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4790
4791 return MatchOperand_Success;
4792}
4793
Jack Carterdc1e35d2012-09-06 20:00:02 +00004794MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
4795
Vladimir Medic4c299852013-11-06 11:27:05 +00004796 MCSymbolRefExpr::VariantKind VK =
4797 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
4798 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
4799 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
4800 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
4801 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
4802 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
4803 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
4804 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
4805 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
4806 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
4807 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
4808 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
4809 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
4810 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
4811 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
4812 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
4813 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
4814 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00004815 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
4816 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
4817 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
4818 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
4819 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
4820 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00004821 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
4822 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00004823 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00004824
Matheus Almeida2852af82014-04-22 10:15:54 +00004825 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00004826
Jack Carterdc1e35d2012-09-06 20:00:02 +00004827 return VK;
4828}
Jack Cartera63b16a2012-09-07 00:23:42 +00004829
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004830/// Sometimes (i.e. load/stores) the operand may be followed immediately by
4831/// either this.
4832/// ::= '(', register, ')'
4833/// handle it before we iterate so we don't get tripped up by the lack of
4834/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004835bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004836 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004837 if (getLexer().is(AsmToken::LParen)) {
4838 Operands.push_back(
4839 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
4840 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004841 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004842 SMLoc Loc = getLexer().getLoc();
4843 Parser.eatToEndOfStatement();
4844 return Error(Loc, "unexpected token in argument list");
4845 }
4846 if (Parser.getTok().isNot(AsmToken::RParen)) {
4847 SMLoc Loc = getLexer().getLoc();
4848 Parser.eatToEndOfStatement();
4849 return Error(Loc, "unexpected token, expected ')'");
4850 }
4851 Operands.push_back(
4852 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
4853 Parser.Lex();
4854 }
4855 return false;
4856}
4857
4858/// Sometimes (i.e. in MSA) the operand may be followed immediately by
4859/// either one of these.
4860/// ::= '[', register, ']'
4861/// ::= '[', integer, ']'
4862/// handle it before we iterate so we don't get tripped up by the lack of
4863/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004864bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00004865 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004866 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004867 if (getLexer().is(AsmToken::LBrac)) {
4868 Operands.push_back(
4869 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
4870 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004871 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004872 SMLoc Loc = getLexer().getLoc();
4873 Parser.eatToEndOfStatement();
4874 return Error(Loc, "unexpected token in argument list");
4875 }
4876 if (Parser.getTok().isNot(AsmToken::RBrac)) {
4877 SMLoc Loc = getLexer().getLoc();
4878 Parser.eatToEndOfStatement();
4879 return Error(Loc, "unexpected token, expected ']'");
4880 }
4881 Operands.push_back(
4882 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
4883 Parser.Lex();
4884 }
4885 return false;
4886}
4887
David Blaikie960ea3f2014-06-08 16:18:35 +00004888bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
4889 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004890 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004891 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004892
4893 // We have reached first instruction, module directive are now forbidden.
4894 getTargetStreamer().forbidModuleDirective();
4895
Vladimir Medic74593e62013-07-17 15:00:42 +00004896 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00004897 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00004898 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00004899 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00004900 }
Vladimir Medic64828a12013-07-16 10:07:14 +00004901 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004902 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004903
4904 // Read the remaining operands.
4905 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4906 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004907 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004908 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004909 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004910 return Error(Loc, "unexpected token in argument list");
4911 }
Toma Tabacu13964452014-09-04 13:23:44 +00004912 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004913 return true;
4914 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00004915
Jack Carterd0bd6422013-04-18 00:41:53 +00004916 while (getLexer().is(AsmToken::Comma)) {
4917 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00004918 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004919 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004920 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004921 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004922 return Error(Loc, "unexpected token in argument list");
4923 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004924 // Parse bracket and parenthesis suffixes before we iterate
4925 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00004926 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004927 return true;
4928 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00004929 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004930 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00004931 }
4932 }
Jack Carterb4dbc172012-09-05 23:34:03 +00004933 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4934 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004935 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004936 return Error(Loc, "unexpected token in argument list");
4937 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004938 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00004939 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00004940}
4941
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004942bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004943 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004944 SMLoc Loc = getLexer().getLoc();
4945 Parser.eatToEndOfStatement();
4946 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00004947}
4948
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004949bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004950 return Error(Loc, ErrorMsg);
4951}
4952
Jack Carter0b744b32012-10-04 02:29:46 +00004953bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004954 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004955 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00004956
4957 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00004958 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00004959
4960 Parser.Lex(); // Eat "noat".
4961
Jack Carterd0bd6422013-04-18 00:41:53 +00004962 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004963 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004964 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004965 return false;
4966 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004967
4968 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004969 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004970 return false;
4971}
Jack Carterd0bd6422013-04-18 00:41:53 +00004972
Jack Carter0b744b32012-10-04 02:29:46 +00004973bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00004974 // Line can be: ".set at", which sets $at to $1
4975 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00004976 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00004977 Parser.Lex(); // Eat "at".
4978
Jack Carter0b744b32012-10-04 02:29:46 +00004979 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004980 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00004981 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00004982
4983 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004984 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004985 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00004986 }
4987
4988 if (getLexer().isNot(AsmToken::Equal)) {
4989 reportParseError("unexpected token, expected equals sign");
4990 return false;
4991 }
4992 Parser.Lex(); // Eat "=".
4993
4994 if (getLexer().isNot(AsmToken::Dollar)) {
4995 if (getLexer().is(AsmToken::EndOfStatement)) {
4996 reportParseError("no register specified");
4997 return false;
4998 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00004999 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00005000 return false;
5001 }
Toma Tabacu16a74492015-02-13 10:30:57 +00005002 }
5003 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00005004
Toma Tabacu16a74492015-02-13 10:30:57 +00005005 // Find out what "reg" is.
5006 unsigned AtRegNo;
5007 const AsmToken &Reg = Parser.getTok();
5008 if (Reg.is(AsmToken::Identifier)) {
5009 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
5010 } else if (Reg.is(AsmToken::Integer)) {
5011 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00005012 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00005013 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00005014 return false;
5015 }
Toma Tabacu16a74492015-02-13 10:30:57 +00005016
5017 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00005018 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00005019 reportParseError("invalid register");
5020 return false;
5021 }
5022 Parser.Lex(); // Eat "reg".
5023
5024 // If this is not the end of the statement, report an error.
5025 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5026 reportParseError("unexpected token, expected end of statement");
5027 return false;
5028 }
5029
5030 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
5031
5032 Parser.Lex(); // Consume the EndOfStatement.
5033 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005034}
5035
5036bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005037 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00005038 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00005039 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005040 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005041 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005042 return false;
5043 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005044 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00005045 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00005046 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005047 return false;
5048}
5049
5050bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005051 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005052 Parser.Lex();
5053 // If this is not the end of the statement, report an error.
5054 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005055 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005056 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00005057 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005058 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00005059 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00005060 Parser.Lex(); // Consume the EndOfStatement.
5061 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005062}
5063
5064bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005065 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00005066 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00005067 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005068 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005069 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005070 return false;
5071 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005072 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00005073 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00005074 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005075 return false;
5076}
5077
5078bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005079 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00005080 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00005081 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005082 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005083 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005084 return false;
5085 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005086 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00005087 reportParseError("`noreorder' must be set before `nomacro'");
5088 return false;
5089 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005090 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00005091 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00005092 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005093 return false;
5094}
Jack Carterd76b2372013-03-21 21:44:16 +00005095
Daniel Sanders44934432014-08-07 12:03:36 +00005096bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005097 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00005098 Parser.Lex();
5099
5100 // If this is not the end of the statement, report an error.
5101 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005102 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00005103
5104 setFeatureBits(Mips::FeatureMSA, "msa");
5105 getTargetStreamer().emitDirectiveSetMsa();
5106 return false;
5107}
5108
5109bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005110 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00005111 Parser.Lex();
5112
5113 // If this is not the end of the statement, report an error.
5114 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005115 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00005116
5117 clearFeatureBits(Mips::FeatureMSA, "msa");
5118 getTargetStreamer().emitDirectiveSetNoMsa();
5119 return false;
5120}
5121
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005122bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005123 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005124 Parser.Lex(); // Eat "nodsp".
5125
5126 // If this is not the end of the statement, report an error.
5127 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5128 reportParseError("unexpected token, expected end of statement");
5129 return false;
5130 }
5131
5132 clearFeatureBits(Mips::FeatureDSP, "dsp");
5133 getTargetStreamer().emitDirectiveSetNoDsp();
5134 return false;
5135}
5136
Toma Tabacucc2502d2014-11-04 17:18:07 +00005137bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005138 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005139 Parser.Lex(); // Eat "mips16".
5140
Jack Carter39536722014-01-22 23:08:42 +00005141 // If this is not the end of the statement, report an error.
5142 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005143 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00005144 return false;
5145 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00005146
5147 setFeatureBits(Mips::FeatureMips16, "mips16");
5148 getTargetStreamer().emitDirectiveSetMips16();
5149 Parser.Lex(); // Consume the EndOfStatement.
5150 return false;
5151}
5152
5153bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005154 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005155 Parser.Lex(); // Eat "nomips16".
5156
5157 // If this is not the end of the statement, report an error.
5158 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5159 reportParseError("unexpected token, expected end of statement");
5160 return false;
5161 }
5162
5163 clearFeatureBits(Mips::FeatureMips16, "mips16");
5164 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00005165 Parser.Lex(); // Consume the EndOfStatement.
5166 return false;
5167}
5168
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005169bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005170 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005171 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005172 // Line can be: .set fp=32
5173 // .set fp=xx
5174 // .set fp=64
5175 Parser.Lex(); // Eat fp token
5176 AsmToken Tok = Parser.getTok();
5177 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005178 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005179 return false;
5180 }
5181 Parser.Lex(); // Eat '=' token.
5182 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005183
5184 if (!parseFpABIValue(FpAbiVal, ".set"))
5185 return false;
5186
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005187 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005188 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005189 return false;
5190 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005191 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005192 Parser.Lex(); // Consume the EndOfStatement.
5193 return false;
5194}
5195
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005196bool MipsAsmParser::parseSetOddSPRegDirective() {
5197 MCAsmParser &Parser = getParser();
5198
5199 Parser.Lex(); // Eat "oddspreg".
5200 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5201 reportParseError("unexpected token, expected end of statement");
5202 return false;
5203 }
5204
5205 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5206 getTargetStreamer().emitDirectiveSetOddSPReg();
5207 return false;
5208}
5209
5210bool MipsAsmParser::parseSetNoOddSPRegDirective() {
5211 MCAsmParser &Parser = getParser();
5212
5213 Parser.Lex(); // Eat "nooddspreg".
5214 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5215 reportParseError("unexpected token, expected end of statement");
5216 return false;
5217 }
5218
5219 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5220 getTargetStreamer().emitDirectiveSetNoOddSPReg();
5221 return false;
5222}
5223
Toma Tabacu9db22db2014-09-09 10:15:38 +00005224bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005225 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005226 SMLoc Loc = getLexer().getLoc();
5227
5228 Parser.Lex();
5229 if (getLexer().isNot(AsmToken::EndOfStatement))
5230 return reportParseError("unexpected token, expected end of statement");
5231
5232 // Always keep an element on the options "stack" to prevent the user
5233 // from changing the initial options. This is how we remember them.
5234 if (AssemblerOptions.size() == 2)
5235 return reportParseError(Loc, ".set pop with no .set push");
5236
Akira Hatanakab11ef082015-11-14 06:35:56 +00005237 MCSubtargetInfo &STI = copySTI();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005238 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005239 setAvailableFeatures(
5240 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
5241 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00005242
5243 getTargetStreamer().emitDirectiveSetPop();
5244 return false;
5245}
5246
5247bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005248 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005249 Parser.Lex();
5250 if (getLexer().isNot(AsmToken::EndOfStatement))
5251 return reportParseError("unexpected token, expected end of statement");
5252
5253 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00005254 AssemblerOptions.push_back(
5255 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00005256
5257 getTargetStreamer().emitDirectiveSetPush();
5258 return false;
5259}
5260
Toma Tabacu29696502015-06-02 09:48:04 +00005261bool MipsAsmParser::parseSetSoftFloatDirective() {
5262 MCAsmParser &Parser = getParser();
5263 Parser.Lex();
5264 if (getLexer().isNot(AsmToken::EndOfStatement))
5265 return reportParseError("unexpected token, expected end of statement");
5266
5267 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5268 getTargetStreamer().emitDirectiveSetSoftFloat();
5269 return false;
5270}
5271
5272bool MipsAsmParser::parseSetHardFloatDirective() {
5273 MCAsmParser &Parser = getParser();
5274 Parser.Lex();
5275 if (getLexer().isNot(AsmToken::EndOfStatement))
5276 return reportParseError("unexpected token, expected end of statement");
5277
5278 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5279 getTargetStreamer().emitDirectiveSetHardFloat();
5280 return false;
5281}
5282
Jack Carterd76b2372013-03-21 21:44:16 +00005283bool MipsAsmParser::parseSetAssignment() {
5284 StringRef Name;
5285 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00005286 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00005287
5288 if (Parser.parseIdentifier(Name))
5289 reportParseError("expected identifier after .set");
5290
5291 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005292 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00005293 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00005294
Jack Carter3b2c96e2014-01-22 23:31:38 +00005295 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00005296 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00005297
Jim Grosbach6f482002015-05-18 18:43:14 +00005298 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00005299 Sym->setVariableValue(Value);
5300
5301 return false;
5302}
Jack Carterd0bd6422013-04-18 00:41:53 +00005303
Toma Tabacu26647792014-09-09 12:52:14 +00005304bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005305 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00005306 Parser.Lex();
5307 if (getLexer().isNot(AsmToken::EndOfStatement))
5308 return reportParseError("unexpected token, expected end of statement");
5309
5310 // Reset assembler options to their initial values.
Akira Hatanakab11ef082015-11-14 06:35:56 +00005311 MCSubtargetInfo &STI = copySTI();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005312 setAvailableFeatures(
5313 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
5314 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00005315 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
5316
5317 getTargetStreamer().emitDirectiveSetMips0();
5318 return false;
5319}
5320
Toma Tabacu85618b32014-08-19 14:22:52 +00005321bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005322 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00005323 Parser.Lex();
5324 if (getLexer().isNot(AsmToken::Equal))
5325 return reportParseError("unexpected token, expected equals sign");
5326
5327 Parser.Lex();
5328 StringRef Arch;
5329 if (Parser.parseIdentifier(Arch))
5330 return reportParseError("expected arch identifier");
5331
5332 StringRef ArchFeatureName =
5333 StringSwitch<StringRef>(Arch)
5334 .Case("mips1", "mips1")
5335 .Case("mips2", "mips2")
5336 .Case("mips3", "mips3")
5337 .Case("mips4", "mips4")
5338 .Case("mips5", "mips5")
5339 .Case("mips32", "mips32")
5340 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005341 .Case("mips32r3", "mips32r3")
5342 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005343 .Case("mips32r6", "mips32r6")
5344 .Case("mips64", "mips64")
5345 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005346 .Case("mips64r3", "mips64r3")
5347 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005348 .Case("mips64r6", "mips64r6")
5349 .Case("cnmips", "cnmips")
5350 .Case("r4000", "mips3") // This is an implementation of Mips3.
5351 .Default("");
5352
5353 if (ArchFeatureName.empty())
5354 return reportParseError("unsupported architecture");
5355
5356 selectArch(ArchFeatureName);
5357 getTargetStreamer().emitDirectiveSetArch(Arch);
5358 return false;
5359}
5360
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005361bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005362 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005363 Parser.Lex();
5364 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005365 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005366
Matheus Almeida2852af82014-04-22 10:15:54 +00005367 switch (Feature) {
5368 default:
5369 llvm_unreachable("Unimplemented feature");
5370 case Mips::FeatureDSP:
5371 setFeatureBits(Mips::FeatureDSP, "dsp");
5372 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005373 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005374 case Mips::FeatureMicroMips:
5375 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005376 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005377 case Mips::FeatureMips1:
5378 selectArch("mips1");
5379 getTargetStreamer().emitDirectiveSetMips1();
5380 break;
5381 case Mips::FeatureMips2:
5382 selectArch("mips2");
5383 getTargetStreamer().emitDirectiveSetMips2();
5384 break;
5385 case Mips::FeatureMips3:
5386 selectArch("mips3");
5387 getTargetStreamer().emitDirectiveSetMips3();
5388 break;
5389 case Mips::FeatureMips4:
5390 selectArch("mips4");
5391 getTargetStreamer().emitDirectiveSetMips4();
5392 break;
5393 case Mips::FeatureMips5:
5394 selectArch("mips5");
5395 getTargetStreamer().emitDirectiveSetMips5();
5396 break;
5397 case Mips::FeatureMips32:
5398 selectArch("mips32");
5399 getTargetStreamer().emitDirectiveSetMips32();
5400 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005401 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005402 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005403 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005404 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005405 case Mips::FeatureMips32r3:
5406 selectArch("mips32r3");
5407 getTargetStreamer().emitDirectiveSetMips32R3();
5408 break;
5409 case Mips::FeatureMips32r5:
5410 selectArch("mips32r5");
5411 getTargetStreamer().emitDirectiveSetMips32R5();
5412 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005413 case Mips::FeatureMips32r6:
5414 selectArch("mips32r6");
5415 getTargetStreamer().emitDirectiveSetMips32R6();
5416 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005417 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005418 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00005419 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005420 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005421 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005422 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005423 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005424 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005425 case Mips::FeatureMips64r3:
5426 selectArch("mips64r3");
5427 getTargetStreamer().emitDirectiveSetMips64R3();
5428 break;
5429 case Mips::FeatureMips64r5:
5430 selectArch("mips64r5");
5431 getTargetStreamer().emitDirectiveSetMips64R5();
5432 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005433 case Mips::FeatureMips64r6:
5434 selectArch("mips64r6");
5435 getTargetStreamer().emitDirectiveSetMips64R6();
5436 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005437 }
5438 return false;
5439}
5440
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005441bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005442 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005443 if (getLexer().isNot(AsmToken::Comma)) {
5444 SMLoc Loc = getLexer().getLoc();
5445 Parser.eatToEndOfStatement();
5446 return Error(Loc, ErrorStr);
5447 }
5448
Matheus Almeida2852af82014-04-22 10:15:54 +00005449 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005450 return true;
5451}
5452
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005453// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
5454// In this class, it is only used for .cprestore.
5455// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
5456// MipsTargetELFStreamer and MipsAsmParser.
5457bool MipsAsmParser::isPicAndNotNxxAbi() {
5458 return inPicMode() && !(isABI_N32() || isABI_N64());
5459}
5460
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005461bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00005462 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00005463 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005464
Toma Tabacudde4c462014-11-06 10:02:45 +00005465 if (inMips16Mode()) {
5466 reportParseError(".cpload is not supported in Mips16 mode");
5467 return false;
5468 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005469
David Blaikie960ea3f2014-06-08 16:18:35 +00005470 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00005471 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005472 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5473 reportParseError("expected register containing function address");
5474 return false;
5475 }
5476
David Blaikie960ea3f2014-06-08 16:18:35 +00005477 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
5478 if (!RegOpnd.isGPRAsmReg()) {
5479 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005480 return false;
5481 }
5482
Toma Tabacudde4c462014-11-06 10:02:45 +00005483 // If this is not the end of the statement, report an error.
5484 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5485 reportParseError("unexpected token, expected end of statement");
5486 return false;
5487 }
5488
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005489 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005490 return false;
5491}
5492
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005493bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
5494 MCAsmParser &Parser = getParser();
5495
5496 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
5497 // is used in non-PIC mode.
5498
5499 if (inMips16Mode()) {
5500 reportParseError(".cprestore is not supported in Mips16 mode");
5501 return false;
5502 }
5503
5504 // Get the stack offset value.
5505 const MCExpr *StackOffset;
5506 int64_t StackOffsetVal;
5507 if (Parser.parseExpression(StackOffset)) {
5508 reportParseError("expected stack offset value");
5509 return false;
5510 }
5511
5512 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
5513 reportParseError("stack offset is not an absolute expression");
5514 return false;
5515 }
5516
5517 if (StackOffsetVal < 0) {
5518 Warning(Loc, ".cprestore with negative stack offset has no effect");
5519 IsCpRestoreSet = false;
5520 } else {
5521 IsCpRestoreSet = true;
5522 CpRestoreOffset = StackOffsetVal;
5523 }
5524
5525 // If this is not the end of the statement, report an error.
5526 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5527 reportParseError("unexpected token, expected end of statement");
5528 return false;
5529 }
5530
5531 // Store the $gp on the stack.
5532 SmallVector<MCInst, 3> StoreInsts;
5533 createCpRestoreMemOp(false /*IsLoad*/, CpRestoreOffset /*StackOffset*/, Loc,
5534 StoreInsts);
5535
5536 getTargetStreamer().emitDirectiveCpRestore(StoreInsts, CpRestoreOffset);
5537 Parser.Lex(); // Consume the EndOfStatement.
5538 return false;
5539}
5540
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005541bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005542 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005543 unsigned FuncReg;
5544 unsigned Save;
5545 bool SaveIsReg = true;
5546
Matheus Almeida7e815762014-06-18 13:08:59 +00005547 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005548 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005549 if (ResTy == MatchOperand_NoMatch) {
5550 reportParseError("expected register containing function address");
5551 Parser.eatToEndOfStatement();
5552 return false;
5553 }
5554
5555 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5556 if (!FuncRegOpnd.isGPRAsmReg()) {
5557 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
5558 Parser.eatToEndOfStatement();
5559 return false;
5560 }
5561
5562 FuncReg = FuncRegOpnd.getGPR32Reg();
5563 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005564
Toma Tabacu65f10572014-09-16 15:00:52 +00005565 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005566 return true;
5567
Toma Tabacu13964452014-09-04 13:23:44 +00005568 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005569 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00005570 const MCExpr *OffsetExpr;
5571 int64_t OffsetVal;
5572 SMLoc ExprLoc = getLexer().getLoc();
5573
5574 if (Parser.parseExpression(OffsetExpr) ||
5575 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
5576 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00005577 Parser.eatToEndOfStatement();
5578 return false;
5579 }
Daniel Sanders5d796282015-09-21 09:26:55 +00005580
5581 Save = OffsetVal;
5582 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00005583 } else {
5584 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5585 if (!SaveOpnd.isGPRAsmReg()) {
5586 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
5587 Parser.eatToEndOfStatement();
5588 return false;
5589 }
5590 Save = SaveOpnd.getGPR32Reg();
5591 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005592
Toma Tabacu65f10572014-09-16 15:00:52 +00005593 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005594 return true;
5595
Toma Tabacu8874eac2015-02-18 13:46:53 +00005596 const MCExpr *Expr;
5597 if (Parser.parseExpression(Expr)) {
5598 reportParseError("expected expression");
5599 return false;
5600 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005601
Toma Tabacu8874eac2015-02-18 13:46:53 +00005602 if (Expr->getKind() != MCExpr::SymbolRef) {
5603 reportParseError("expected symbol");
5604 return false;
5605 }
5606 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
5607
Daniel Sandersf173dda2015-09-22 10:50:09 +00005608 CpSaveLocation = Save;
5609 CpSaveLocationIsRegister = SaveIsReg;
5610
Toma Tabacu8874eac2015-02-18 13:46:53 +00005611 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
5612 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005613 return false;
5614}
5615
Daniel Sandersf173dda2015-09-22 10:50:09 +00005616bool MipsAsmParser::parseDirectiveCPReturn() {
5617 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
5618 CpSaveLocationIsRegister);
5619 return false;
5620}
5621
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005622bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005623 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005624 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5625 const AsmToken &Tok = Parser.getTok();
5626
5627 if (Tok.getString() == "2008") {
5628 Parser.Lex();
5629 getTargetStreamer().emitDirectiveNaN2008();
5630 return false;
5631 } else if (Tok.getString() == "legacy") {
5632 Parser.Lex();
5633 getTargetStreamer().emitDirectiveNaNLegacy();
5634 return false;
5635 }
5636 }
5637 // If we don't recognize the option passed to the .nan
5638 // directive (e.g. no option or unknown option), emit an error.
5639 reportParseError("invalid option in .nan directive");
5640 return false;
5641}
5642
Jack Carter0b744b32012-10-04 02:29:46 +00005643bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005644 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005645 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00005646 const AsmToken &Tok = Parser.getTok();
5647
5648 if (Tok.getString() == "noat") {
5649 return parseSetNoAtDirective();
5650 } else if (Tok.getString() == "at") {
5651 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00005652 } else if (Tok.getString() == "arch") {
5653 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005654 } else if (Tok.getString() == "fp") {
5655 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005656 } else if (Tok.getString() == "oddspreg") {
5657 return parseSetOddSPRegDirective();
5658 } else if (Tok.getString() == "nooddspreg") {
5659 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005660 } else if (Tok.getString() == "pop") {
5661 return parseSetPopDirective();
5662 } else if (Tok.getString() == "push") {
5663 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00005664 } else if (Tok.getString() == "reorder") {
5665 return parseSetReorderDirective();
5666 } else if (Tok.getString() == "noreorder") {
5667 return parseSetNoReorderDirective();
5668 } else if (Tok.getString() == "macro") {
5669 return parseSetMacroDirective();
5670 } else if (Tok.getString() == "nomacro") {
5671 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00005672 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00005673 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005674 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00005675 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005676 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00005677 getTargetStreamer().emitDirectiveSetNoMicroMips();
5678 Parser.eatToEndOfStatement();
5679 return false;
5680 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005681 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00005682 } else if (Tok.getString() == "mips0") {
5683 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00005684 } else if (Tok.getString() == "mips1") {
5685 return parseSetFeature(Mips::FeatureMips1);
5686 } else if (Tok.getString() == "mips2") {
5687 return parseSetFeature(Mips::FeatureMips2);
5688 } else if (Tok.getString() == "mips3") {
5689 return parseSetFeature(Mips::FeatureMips3);
5690 } else if (Tok.getString() == "mips4") {
5691 return parseSetFeature(Mips::FeatureMips4);
5692 } else if (Tok.getString() == "mips5") {
5693 return parseSetFeature(Mips::FeatureMips5);
5694 } else if (Tok.getString() == "mips32") {
5695 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00005696 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005697 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005698 } else if (Tok.getString() == "mips32r3") {
5699 return parseSetFeature(Mips::FeatureMips32r3);
5700 } else if (Tok.getString() == "mips32r5") {
5701 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005702 } else if (Tok.getString() == "mips32r6") {
5703 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005704 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005705 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005706 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005707 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005708 } else if (Tok.getString() == "mips64r3") {
5709 return parseSetFeature(Mips::FeatureMips64r3);
5710 } else if (Tok.getString() == "mips64r5") {
5711 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005712 } else if (Tok.getString() == "mips64r6") {
5713 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00005714 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005715 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005716 } else if (Tok.getString() == "nodsp") {
5717 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00005718 } else if (Tok.getString() == "msa") {
5719 return parseSetMsaDirective();
5720 } else if (Tok.getString() == "nomsa") {
5721 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00005722 } else if (Tok.getString() == "softfloat") {
5723 return parseSetSoftFloatDirective();
5724 } else if (Tok.getString() == "hardfloat") {
5725 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00005726 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00005727 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00005728 parseSetAssignment();
5729 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005730 }
Jack Carter07c818d2013-01-25 01:31:34 +00005731
Jack Carter0b744b32012-10-04 02:29:46 +00005732 return true;
5733}
5734
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005735/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00005736/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005737bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005738 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005739 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5740 for (;;) {
5741 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005742 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00005743 return true;
5744
5745 getParser().getStreamer().EmitValue(Value, Size);
5746
5747 if (getLexer().is(AsmToken::EndOfStatement))
5748 break;
5749
Jack Carter07c818d2013-01-25 01:31:34 +00005750 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005751 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00005752 Parser.Lex();
5753 }
5754 }
5755
5756 Parser.Lex();
5757 return false;
5758}
5759
Vladimir Medic4c299852013-11-06 11:27:05 +00005760/// parseDirectiveGpWord
5761/// ::= .gpword local_sym
5762bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005763 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00005764 const MCExpr *Value;
5765 // EmitGPRel32Value requires an expression, so we are using base class
5766 // method to evaluate the expression.
5767 if (getParser().parseExpression(Value))
5768 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00005769 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00005770
Vladimir Medice10c1122013-11-13 13:18:04 +00005771 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005772 return Error(getLexer().getLoc(),
5773 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00005774 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00005775 return false;
5776}
5777
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005778/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00005779/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005780bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005781 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005782 const MCExpr *Value;
5783 // EmitGPRel64Value requires an expression, so we are using base class
5784 // method to evaluate the expression.
5785 if (getParser().parseExpression(Value))
5786 return true;
5787 getParser().getStreamer().EmitGPRel64Value(Value);
5788
5789 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005790 return Error(getLexer().getLoc(),
5791 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00005792 Parser.Lex(); // Eat EndOfStatement token.
5793 return false;
5794}
5795
Jack Carter0cd3c192014-01-06 23:27:31 +00005796bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005797 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00005798 // Get the option token.
5799 AsmToken Tok = Parser.getTok();
5800 // At the moment only identifiers are supported.
5801 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005802 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00005803 Parser.eatToEndOfStatement();
5804 return false;
5805 }
5806
5807 StringRef Option = Tok.getIdentifier();
5808
5809 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005810 // MipsAsmParser needs to know if the current PIC mode changes.
5811 IsPicEnabled = false;
5812
Jack Carter0cd3c192014-01-06 23:27:31 +00005813 getTargetStreamer().emitDirectiveOptionPic0();
5814 Parser.Lex();
5815 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5816 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005817 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005818 Parser.eatToEndOfStatement();
5819 }
5820 return false;
5821 }
5822
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005823 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005824 // MipsAsmParser needs to know if the current PIC mode changes.
5825 IsPicEnabled = true;
5826
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005827 getTargetStreamer().emitDirectiveOptionPic2();
5828 Parser.Lex();
5829 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5830 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005831 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005832 Parser.eatToEndOfStatement();
5833 }
5834 return false;
5835 }
5836
Jack Carter0cd3c192014-01-06 23:27:31 +00005837 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00005838 Warning(Parser.getTok().getLoc(),
5839 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00005840 Parser.eatToEndOfStatement();
5841 return false;
5842}
5843
Toma Tabacu9ca50962015-04-16 09:53:47 +00005844/// parseInsnDirective
5845/// ::= .insn
5846bool MipsAsmParser::parseInsnDirective() {
5847 // If this is not the end of the statement, report an error.
5848 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5849 reportParseError("unexpected token, expected end of statement");
5850 return false;
5851 }
5852
5853 // The actual label marking happens in
5854 // MipsELFStreamer::createPendingLabelRelocs().
5855 getTargetStreamer().emitDirectiveInsn();
5856
5857 getParser().Lex(); // Eat EndOfStatement token.
5858 return false;
5859}
5860
Simon Atanasyanbe186202016-02-11 06:45:54 +00005861/// parseSSectionDirective
5862/// ::= .sbss
5863/// ::= .sdata
5864bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) {
5865 // If this is not the end of the statement, report an error.
5866 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5867 reportParseError("unexpected token, expected end of statement");
5868 return false;
5869 }
5870
5871 MCSection *ELFSection = getContext().getELFSection(
5872 Section, Type, ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL);
5873 getParser().getStreamer().SwitchSection(ELFSection);
5874
5875 getParser().Lex(); // Eat EndOfStatement token.
5876 return false;
5877}
5878
Daniel Sanders7e527422014-07-10 13:38:23 +00005879/// parseDirectiveModule
5880/// ::= .module oddspreg
5881/// ::= .module nooddspreg
5882/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00005883/// ::= .module softfloat
5884/// ::= .module hardfloat
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005885bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005886 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005887 MCAsmLexer &Lexer = getLexer();
5888 SMLoc L = Lexer.getLoc();
5889
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00005890 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005891 // TODO : get a better message.
5892 reportParseError(".module directive must appear before any code");
5893 return false;
5894 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005895
Toma Tabacuc405c822015-01-23 10:40:19 +00005896 StringRef Option;
5897 if (Parser.parseIdentifier(Option)) {
5898 reportParseError("expected .module option identifier");
5899 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005900 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005901
Toma Tabacuc405c822015-01-23 10:40:19 +00005902 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005903 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005904
Toma Tabacu3c499582015-06-25 10:56:57 +00005905 // Synchronize the abiflags information with the FeatureBits information we
5906 // changed above.
5907 getTargetStreamer().updateABIInfo(*this);
5908
5909 // If printing assembly, use the recently updated abiflags information.
5910 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5911 // emitted at the end).
5912 getTargetStreamer().emitDirectiveModuleOddSPReg();
5913
Toma Tabacuc405c822015-01-23 10:40:19 +00005914 // If this is not the end of the statement, report an error.
5915 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5916 reportParseError("unexpected token, expected end of statement");
5917 return false;
5918 }
5919
5920 return false; // parseDirectiveModule has finished successfully.
5921 } else if (Option == "nooddspreg") {
5922 if (!isABI_O32()) {
5923 Error(L, "'.module nooddspreg' requires the O32 ABI");
5924 return false;
5925 }
5926
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005927 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005928
Toma Tabacu3c499582015-06-25 10:56:57 +00005929 // Synchronize the abiflags information with the FeatureBits information we
5930 // changed above.
5931 getTargetStreamer().updateABIInfo(*this);
5932
5933 // If printing assembly, use the recently updated abiflags information.
5934 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5935 // emitted at the end).
5936 getTargetStreamer().emitDirectiveModuleOddSPReg();
5937
Toma Tabacuc405c822015-01-23 10:40:19 +00005938 // If this is not the end of the statement, report an error.
5939 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5940 reportParseError("unexpected token, expected end of statement");
5941 return false;
5942 }
5943
5944 return false; // parseDirectiveModule has finished successfully.
5945 } else if (Option == "fp") {
5946 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00005947 } else if (Option == "softfloat") {
5948 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5949
5950 // Synchronize the ABI Flags information with the FeatureBits information we
5951 // updated above.
5952 getTargetStreamer().updateABIInfo(*this);
5953
5954 // If printing assembly, use the recently updated ABI Flags information.
5955 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5956 // emitted later).
5957 getTargetStreamer().emitDirectiveModuleSoftFloat();
5958
5959 // If this is not the end of the statement, report an error.
5960 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5961 reportParseError("unexpected token, expected end of statement");
5962 return false;
5963 }
5964
5965 return false; // parseDirectiveModule has finished successfully.
5966 } else if (Option == "hardfloat") {
5967 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5968
5969 // Synchronize the ABI Flags information with the FeatureBits information we
5970 // updated above.
5971 getTargetStreamer().updateABIInfo(*this);
5972
5973 // If printing assembly, use the recently updated ABI Flags information.
5974 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5975 // emitted later).
5976 getTargetStreamer().emitDirectiveModuleHardFloat();
5977
5978 // If this is not the end of the statement, report an error.
5979 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5980 reportParseError("unexpected token, expected end of statement");
5981 return false;
5982 }
5983
5984 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00005985 } else {
5986 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
5987 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005988}
5989
5990/// parseDirectiveModuleFP
5991/// ::= =32
5992/// ::= =xx
5993/// ::= =64
5994bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005995 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005996 MCAsmLexer &Lexer = getLexer();
5997
5998 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005999 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006000 return false;
6001 }
6002 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006003
Daniel Sanders7e527422014-07-10 13:38:23 +00006004 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006005 if (!parseFpABIValue(FpABI, ".module"))
6006 return false;
6007
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006008 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006009 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006010 return false;
6011 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006012
Toma Tabacua64e5402015-06-25 12:44:38 +00006013 // Synchronize the abiflags information with the FeatureBits information we
6014 // changed above.
6015 getTargetStreamer().updateABIInfo(*this);
6016
6017 // If printing assembly, use the recently updated abiflags information.
6018 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
6019 // emitted at the end).
6020 getTargetStreamer().emitDirectiveModuleFP();
6021
Daniel Sanders7e527422014-07-10 13:38:23 +00006022 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006023 return false;
6024}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006025
Daniel Sanders7e527422014-07-10 13:38:23 +00006026bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006027 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006028 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006029 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006030 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006031
6032 if (Lexer.is(AsmToken::Identifier)) {
6033 StringRef Value = Parser.getTok().getString();
6034 Parser.Lex();
6035
6036 if (Value != "xx") {
6037 reportParseError("unsupported value, expected 'xx', '32' or '64'");
6038 return false;
6039 }
6040
6041 if (!isABI_O32()) {
6042 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
6043 return false;
6044 }
6045
Daniel Sanders7e527422014-07-10 13:38:23 +00006046 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006047 if (ModuleLevelOptions) {
6048 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6049 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6050 } else {
6051 setFeatureBits(Mips::FeatureFPXX, "fpxx");
6052 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
6053 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006054 return true;
6055 }
6056
6057 if (Lexer.is(AsmToken::Integer)) {
6058 unsigned Value = Parser.getTok().getIntVal();
6059 Parser.Lex();
6060
6061 if (Value != 32 && Value != 64) {
6062 reportParseError("unsupported value, expected 'xx', '32' or '64'");
6063 return false;
6064 }
6065
6066 if (Value == 32) {
6067 if (!isABI_O32()) {
6068 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
6069 return false;
6070 }
6071
Daniel Sanders7e527422014-07-10 13:38:23 +00006072 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006073 if (ModuleLevelOptions) {
6074 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6075 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6076 } else {
6077 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
6078 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
6079 }
Toma Tabacua64e5402015-06-25 12:44:38 +00006080 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00006081 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006082 if (ModuleLevelOptions) {
6083 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6084 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6085 } else {
6086 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
6087 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
6088 }
Toma Tabacua64e5402015-06-25 12:44:38 +00006089 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006090
Daniel Sanders7e527422014-07-10 13:38:23 +00006091 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006092 }
6093
6094 return false;
6095}
6096
Jack Carter0b744b32012-10-04 02:29:46 +00006097bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006098 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00006099 StringRef IDVal = DirectiveID.getString();
6100
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006101 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00006102 return parseDirectiveCpLoad(DirectiveID.getLoc());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006103 if (IDVal == ".cprestore")
6104 return parseDirectiveCpRestore(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00006105 if (IDVal == ".dword") {
6106 parseDataDirective(8, DirectiveID.getLoc());
6107 return false;
6108 }
Jack Carterd0bd6422013-04-18 00:41:53 +00006109 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006110 StringRef SymbolName;
6111
6112 if (Parser.parseIdentifier(SymbolName)) {
6113 reportParseError("expected identifier after .ent");
6114 return false;
6115 }
6116
6117 // There's an undocumented extension that allows an integer to
6118 // follow the name of the procedure which AFAICS is ignored by GAS.
6119 // Example: .ent foo,2
6120 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6121 if (getLexer().isNot(AsmToken::Comma)) {
6122 // Even though we accept this undocumented extension for compatibility
6123 // reasons, the additional integer argument does not actually change
6124 // the behaviour of the '.ent' directive, so we would like to discourage
6125 // its use. We do this by not referring to the extended version in
6126 // error messages which are not directly related to its use.
6127 reportParseError("unexpected token, expected end of statement");
6128 return false;
6129 }
6130 Parser.Lex(); // Eat the comma.
6131 const MCExpr *DummyNumber;
6132 int64_t DummyNumberVal;
6133 // If the user was explicitly trying to use the extended version,
6134 // we still give helpful extension-related error messages.
6135 if (Parser.parseExpression(DummyNumber)) {
6136 reportParseError("expected number after comma");
6137 return false;
6138 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00006139 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006140 reportParseError("expected an absolute expression after comma");
6141 return false;
6142 }
6143 }
6144
6145 // If this is not the end of the statement, report an error.
6146 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6147 reportParseError("unexpected token, expected end of statement");
6148 return false;
6149 }
6150
Jim Grosbach6f482002015-05-18 18:43:14 +00006151 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006152
6153 getTargetStreamer().emitDirectiveEnt(*Sym);
6154 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006155 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006156 return false;
6157 }
6158
Jack Carter07c818d2013-01-25 01:31:34 +00006159 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006160 StringRef SymbolName;
6161
6162 if (Parser.parseIdentifier(SymbolName)) {
6163 reportParseError("expected identifier after .end");
6164 return false;
6165 }
6166
6167 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6168 reportParseError("unexpected token, expected end of statement");
6169 return false;
6170 }
6171
6172 if (CurrentFn == nullptr) {
6173 reportParseError(".end used without .ent");
6174 return false;
6175 }
6176
6177 if ((SymbolName != CurrentFn->getName())) {
6178 reportParseError(".end symbol does not match .ent symbol");
6179 return false;
6180 }
6181
6182 getTargetStreamer().emitDirectiveEnd(SymbolName);
6183 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006184 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006185 return false;
6186 }
6187
Jack Carter07c818d2013-01-25 01:31:34 +00006188 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006189 // .frame $stack_reg, frame_size_in_bytes, $return_reg
6190 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00006191 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006192 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6193 reportParseError("expected stack register");
6194 return false;
6195 }
6196
6197 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6198 if (!StackRegOpnd.isGPRAsmReg()) {
6199 reportParseError(StackRegOpnd.getStartLoc(),
6200 "expected general purpose register");
6201 return false;
6202 }
6203 unsigned StackReg = StackRegOpnd.getGPR32Reg();
6204
6205 if (Parser.getTok().is(AsmToken::Comma))
6206 Parser.Lex();
6207 else {
6208 reportParseError("unexpected token, expected comma");
6209 return false;
6210 }
6211
6212 // Parse the frame size.
6213 const MCExpr *FrameSize;
6214 int64_t FrameSizeVal;
6215
6216 if (Parser.parseExpression(FrameSize)) {
6217 reportParseError("expected frame size value");
6218 return false;
6219 }
6220
Jim Grosbach13760bd2015-05-30 01:25:56 +00006221 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006222 reportParseError("frame size not an absolute expression");
6223 return false;
6224 }
6225
6226 if (Parser.getTok().is(AsmToken::Comma))
6227 Parser.Lex();
6228 else {
6229 reportParseError("unexpected token, expected comma");
6230 return false;
6231 }
6232
6233 // Parse the return register.
6234 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00006235 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006236 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6237 reportParseError("expected return register");
6238 return false;
6239 }
6240
6241 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6242 if (!ReturnRegOpnd.isGPRAsmReg()) {
6243 reportParseError(ReturnRegOpnd.getStartLoc(),
6244 "expected general purpose register");
6245 return false;
6246 }
6247
6248 // If this is not the end of the statement, report an error.
6249 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6250 reportParseError("unexpected token, expected end of statement");
6251 return false;
6252 }
6253
6254 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
6255 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006256 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006257 return false;
6258 }
6259
Jack Carter07c818d2013-01-25 01:31:34 +00006260 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00006261 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00006262 }
6263
Daniel Sandersd97a6342014-08-13 10:07:34 +00006264 if (IDVal == ".mask" || IDVal == ".fmask") {
6265 // .mask bitmask, frame_offset
6266 // bitmask: One bit for each register used.
6267 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
6268 // first register is expected to be saved.
6269 // Examples:
6270 // .mask 0x80000000, -4
6271 // .fmask 0x80000000, -4
6272 //
Jack Carterbe332172012-09-07 00:48:02 +00006273
Daniel Sandersd97a6342014-08-13 10:07:34 +00006274 // Parse the bitmask
6275 const MCExpr *BitMask;
6276 int64_t BitMaskVal;
6277
6278 if (Parser.parseExpression(BitMask)) {
6279 reportParseError("expected bitmask value");
6280 return false;
6281 }
6282
Jim Grosbach13760bd2015-05-30 01:25:56 +00006283 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006284 reportParseError("bitmask not an absolute expression");
6285 return false;
6286 }
6287
6288 if (Parser.getTok().is(AsmToken::Comma))
6289 Parser.Lex();
6290 else {
6291 reportParseError("unexpected token, expected comma");
6292 return false;
6293 }
6294
6295 // Parse the frame_offset
6296 const MCExpr *FrameOffset;
6297 int64_t FrameOffsetVal;
6298
6299 if (Parser.parseExpression(FrameOffset)) {
6300 reportParseError("expected frame offset value");
6301 return false;
6302 }
6303
Jim Grosbach13760bd2015-05-30 01:25:56 +00006304 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006305 reportParseError("frame offset not an absolute expression");
6306 return false;
6307 }
6308
6309 // If this is not the end of the statement, report an error.
6310 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6311 reportParseError("unexpected token, expected end of statement");
6312 return false;
6313 }
6314
6315 if (IDVal == ".mask")
6316 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
6317 else
6318 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00006319 return false;
6320 }
6321
Matheus Almeida0051f2d2014-04-16 15:48:55 +00006322 if (IDVal == ".nan")
6323 return parseDirectiveNaN();
6324
Jack Carter07c818d2013-01-25 01:31:34 +00006325 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00006326 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00006327 return false;
6328 }
6329
Rafael Espindolab59fb732014-03-28 18:50:26 +00006330 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00006331 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00006332 return false;
6333 }
6334
Jack Carter07c818d2013-01-25 01:31:34 +00006335 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00006336 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00006337 return false;
6338 }
6339
Scott Egertond1aeb052016-02-15 16:11:51 +00006340 if (IDVal == ".hword") {
6341 parseDataDirective(2, DirectiveID.getLoc());
6342 return false;
6343 }
6344
Jack Carter0cd3c192014-01-06 23:27:31 +00006345 if (IDVal == ".option")
6346 return parseDirectiveOption();
6347
6348 if (IDVal == ".abicalls") {
6349 getTargetStreamer().emitDirectiveAbiCalls();
6350 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006351 Error(Parser.getTok().getLoc(),
6352 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00006353 // Clear line
6354 Parser.eatToEndOfStatement();
6355 }
6356 return false;
6357 }
6358
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006359 if (IDVal == ".cpsetup")
6360 return parseDirectiveCPSetup();
6361
Daniel Sandersf173dda2015-09-22 10:50:09 +00006362 if (IDVal == ".cpreturn")
6363 return parseDirectiveCPReturn();
6364
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006365 if (IDVal == ".module")
6366 return parseDirectiveModule();
6367
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00006368 if (IDVal == ".llvm_internal_mips_reallow_module_directive")
6369 return parseInternalDirectiveReallowModule();
6370
Toma Tabacu9ca50962015-04-16 09:53:47 +00006371 if (IDVal == ".insn")
6372 return parseInsnDirective();
6373
Simon Atanasyanbe186202016-02-11 06:45:54 +00006374 if (IDVal == ".sbss")
6375 return parseSSectionDirective(IDVal, ELF::SHT_NOBITS);
6376 if (IDVal == ".sdata")
6377 return parseSSectionDirective(IDVal, ELF::SHT_PROGBITS);
6378
Rafael Espindola870c4e92012-01-11 03:56:41 +00006379 return true;
6380}
6381
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00006382bool MipsAsmParser::parseInternalDirectiveReallowModule() {
6383 // If this is not the end of the statement, report an error.
6384 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6385 reportParseError("unexpected token, expected end of statement");
6386 return false;
6387 }
6388
6389 getTargetStreamer().reallowModuleDirective();
6390
6391 getParser().Lex(); // Eat EndOfStatement token.
6392 return false;
6393}
6394
Rafael Espindola870c4e92012-01-11 03:56:41 +00006395extern "C" void LLVMInitializeMipsAsmParser() {
6396 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
6397 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
6398 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
6399 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
6400}
Jack Carterb4dbc172012-09-05 23:34:03 +00006401
6402#define GET_REGISTER_MATCHER
6403#define GET_MATCHER_IMPLEMENTATION
6404#include "MipsGenAsmMatcher.inc"