blob: 01664373fb6133d14ed5904a8d98711bec91e4f3 [file] [log] [blame]
Jia Liu9f610112012-02-17 08:55:11 +00001//===-- MipsAsmParser.cpp - Parse Mips assembly to MCInst instructions ----===//
Rafael Espindola870c4e92012-01-11 03:56:41 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Eric Christophera5762812015-01-26 17:33:46 +000010#include "MCTargetDesc/MipsABIInfo.h"
Petar Jovanovica5da5882014-02-04 18:41:57 +000011#include "MCTargetDesc/MipsMCExpr.h"
Rafael Espindola870c4e92012-01-11 03:56:41 +000012#include "MCTargetDesc/MipsMCTargetDesc.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000013#include "MipsRegisterInfo.h"
Daniel Sandersa6994442015-08-18 12:33:54 +000014#include "MipsTargetObjectFile.h"
Rafael Espindolaa17151a2013-10-08 13:08:17 +000015#include "MipsTargetStreamer.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000016#include "llvm/ADT/APInt.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000017#include "llvm/ADT/SmallVector.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000018#include "llvm/ADT/StringSwitch.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000019#include "llvm/MC/MCContext.h"
20#include "llvm/MC/MCExpr.h"
21#include "llvm/MC/MCInst.h"
Daniel Sandersa771fef2014-03-24 14:05:39 +000022#include "llvm/MC/MCInstBuilder.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000023#include "llvm/MC/MCParser/MCAsmLexer.h"
24#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Benjamin Kramerb3e8a6d2016-01-27 10:01:28 +000025#include "llvm/MC/MCParser/MCTargetAsmParser.h"
Simon Atanasyanbe186202016-02-11 06:45:54 +000026#include "llvm/MC/MCSectionELF.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000027#include "llvm/MC/MCStreamer.h"
28#include "llvm/MC/MCSubtargetInfo.h"
29#include "llvm/MC/MCSymbol.h"
Daniel Sandersb50ccf82014-04-01 10:35:28 +000030#include "llvm/Support/Debug.h"
Simon Atanasyanbe186202016-02-11 06:45:54 +000031#include "llvm/Support/ELF.h"
Matheus Almeidae0d75aa2013-12-13 11:11:02 +000032#include "llvm/Support/MathExtras.h"
Daniel Sandersef638fe2014-10-03 15:37:37 +000033#include "llvm/Support/SourceMgr.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000034#include "llvm/Support/TargetRegistry.h"
Benjamin Kramer799003b2015-03-23 19:32:43 +000035#include "llvm/Support/raw_ostream.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000036#include <memory>
Rafael Espindola870c4e92012-01-11 03:56:41 +000037
38using namespace llvm;
39
Chandler Carruthe96dd892014-04-21 22:55:11 +000040#define DEBUG_TYPE "mips-asm-parser"
41
Joey Gouly0e76fa72013-09-12 10:28:05 +000042namespace llvm {
43class MCInstrInfo;
44}
45
Rafael Espindola870c4e92012-01-11 03:56:41 +000046namespace {
Jack Carter0b744b32012-10-04 02:29:46 +000047class MipsAssemblerOptions {
48public:
Toma Tabacu465acfd2015-06-09 13:33:26 +000049 MipsAssemblerOptions(const FeatureBitset &Features_) :
Toma Tabacu9db22db2014-09-09 10:15:38 +000050 ATReg(1), Reorder(true), Macro(true), Features(Features_) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000051
Toma Tabacu9db22db2014-09-09 10:15:38 +000052 MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
Toma Tabacub19cf202015-04-27 13:12:59 +000053 ATReg = Opts->getATRegIndex();
Toma Tabacu9db22db2014-09-09 10:15:38 +000054 Reorder = Opts->isReorder();
55 Macro = Opts->isMacro();
56 Features = Opts->getFeatures();
57 }
58
Toma Tabacub19cf202015-04-27 13:12:59 +000059 unsigned getATRegIndex() const { return ATReg; }
60 bool setATRegIndex(unsigned Reg) {
Toma Tabacu92dbbf12015-03-26 13:08:55 +000061 if (Reg > 31)
62 return false;
63
64 ATReg = Reg;
65 return true;
66 }
Jack Carter0b744b32012-10-04 02:29:46 +000067
Toma Tabacu9db22db2014-09-09 10:15:38 +000068 bool isReorder() const { return Reorder; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000069 void setReorder() { Reorder = true; }
70 void setNoReorder() { Reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000071
Toma Tabacu9db22db2014-09-09 10:15:38 +000072 bool isMacro() const { return Macro; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000073 void setMacro() { Macro = true; }
74 void setNoMacro() { Macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000075
Toma Tabacu465acfd2015-06-09 13:33:26 +000076 const FeatureBitset &getFeatures() const { return Features; }
77 void setFeatures(const FeatureBitset &Features_) { Features = Features_; }
Toma Tabacu9db22db2014-09-09 10:15:38 +000078
Daniel Sandersf0df2212014-08-04 12:20:00 +000079 // Set of features that are either architecture features or referenced
80 // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6).
81 // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
82 // The reason we need this mask is explained in the selectArch function.
83 // FIXME: Ideally we would like TableGen to generate this information.
Michael Kupersteindb0712f2015-05-26 10:47:10 +000084 static const FeatureBitset AllArchRelatedMask;
Daniel Sandersf0df2212014-08-04 12:20:00 +000085
Jack Carter0b744b32012-10-04 02:29:46 +000086private:
Toma Tabacu3c24b042014-09-05 15:43:21 +000087 unsigned ATReg;
88 bool Reorder;
89 bool Macro;
Toma Tabacu465acfd2015-06-09 13:33:26 +000090 FeatureBitset Features;
Jack Carter0b744b32012-10-04 02:29:46 +000091};
92}
93
Michael Kupersteindb0712f2015-05-26 10:47:10 +000094const FeatureBitset MipsAssemblerOptions::AllArchRelatedMask = {
95 Mips::FeatureMips1, Mips::FeatureMips2, Mips::FeatureMips3,
96 Mips::FeatureMips3_32, Mips::FeatureMips3_32r2, Mips::FeatureMips4,
97 Mips::FeatureMips4_32, Mips::FeatureMips4_32r2, Mips::FeatureMips5,
98 Mips::FeatureMips5_32r2, Mips::FeatureMips32, Mips::FeatureMips32r2,
99 Mips::FeatureMips32r3, Mips::FeatureMips32r5, Mips::FeatureMips32r6,
100 Mips::FeatureMips64, Mips::FeatureMips64r2, Mips::FeatureMips64r3,
101 Mips::FeatureMips64r5, Mips::FeatureMips64r6, Mips::FeatureCnMips,
102 Mips::FeatureFP64Bit, Mips::FeatureGP64Bit, Mips::FeatureNaN2008
103};
104
Jack Carter0b744b32012-10-04 02:29:46 +0000105namespace {
Rafael Espindola870c4e92012-01-11 03:56:41 +0000106class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000107 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola961d4692014-11-11 05:18:41 +0000108 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000109 return static_cast<MipsTargetStreamer &>(TS);
110 }
111
Eric Christophera5762812015-01-26 17:33:46 +0000112 MipsABIInfo ABI;
Toma Tabacu9db22db2014-09-09 10:15:38 +0000113 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
Daniel Sandersd97a6342014-08-13 10:07:34 +0000114 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
115 // nullptr, which indicates that no function is currently
116 // selected. This usually happens after an '.end func'
117 // directive.
Toma Tabacud88d79c2015-06-23 14:39:42 +0000118 bool IsLittleEndian;
Daniel Sandersa6994442015-08-18 12:33:54 +0000119 bool IsPicEnabled;
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000120 bool IsCpRestoreSet;
121 int CpRestoreOffset;
Daniel Sandersf173dda2015-09-22 10:50:09 +0000122 unsigned CpSaveLocation;
123 /// If true, then CpSaveLocation is a register, otherwise it's an offset.
124 bool CpSaveLocationIsRegister;
Jack Carter0b744b32012-10-04 02:29:46 +0000125
Daniel Sandersef638fe2014-10-03 15:37:37 +0000126 // Print a warning along with its fix-it message at the given range.
127 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
128 SMRange Range, bool ShowColors = true);
129
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000130#define GET_ASSEMBLER_HEADER
131#include "MipsGenAsmMatcher.inc"
132
Matheus Almeida595fcab2014-06-11 15:05:56 +0000133 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
134
Chad Rosier49963552012-10-13 00:26:04 +0000135 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000136 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000137 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000138 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000139
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000140 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000141 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000142
Toma Tabacu13964452014-09-04 13:23:44 +0000143 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000144
Toma Tabacu13964452014-09-04 13:23:44 +0000145 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000146
David Blaikie960ea3f2014-06-08 16:18:35 +0000147 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
148 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000149
Craig Topper56c590a2014-04-29 07:58:02 +0000150 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000151
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000152 OperandMatchResultTy parseMemOperand(OperandVector &Operands);
153 OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000154 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000155 StringRef Identifier, SMLoc S);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000156 OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands,
157 SMLoc S);
158 OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
159 OperandMatchResultTy parseImm(OperandVector &Operands);
160 OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
161 OperandMatchResultTy parseInvNum(OperandVector &Operands);
162 OperandMatchResultTy parseLSAImm(OperandVector &Operands);
163 OperandMatchResultTy parseRegisterPair(OperandVector &Operands);
164 OperandMatchResultTy parseMovePRegPair(OperandVector &Operands);
165 OperandMatchResultTy parseRegisterList(OperandVector &Operands);
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000166
David Blaikie960ea3f2014-06-08 16:18:35 +0000167 bool searchSymbolAlias(OperandVector &Operands);
168
Toma Tabacu13964452014-09-04 13:23:44 +0000169 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000170
Daniel Sanders5bf6eab2015-10-26 23:50:00 +0000171 enum MacroExpanderResultTy {
172 MER_NotAMacro,
173 MER_Success,
174 MER_Fail,
175 };
Jack Carter30a59822012-10-04 04:03:53 +0000176
Matheus Almeida3813d572014-06-19 14:39:14 +0000177 // Expands assembly pseudo instructions.
Daniel Sanders5bf6eab2015-10-26 23:50:00 +0000178 MacroExpanderResultTy
179 tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
180 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000181
Toma Tabacu8f6603a2015-01-30 11:18:50 +0000182 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
183 SmallVectorImpl<MCInst> &Instructions);
184
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000185 bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000186 bool Is32BitImm, bool IsAddress, SMLoc IDLoc,
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000187 SmallVectorImpl<MCInst> &Instructions);
188
Toma Tabacuf712ede2015-06-17 14:31:51 +0000189 bool loadAndAddSymbolAddress(const MCExpr *SymExpr, unsigned DstReg,
190 unsigned SrcReg, bool Is32BitSym, SMLoc IDLoc,
191 SmallVectorImpl<MCInst> &Instructions);
Toma Tabacu674825c2015-06-16 12:16:24 +0000192
Toma Tabacu00e98672015-05-01 12:19:27 +0000193 bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000194 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000195
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000196 bool expandLoadAddress(unsigned DstReg, unsigned BaseReg,
197 const MCOperand &Offset, bool Is32BitAddress,
198 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000199
Jozef Kolek5cfebdd2015-01-21 12:39:30 +0000200 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
201 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000202
Jack Carter9e65aa32013-03-22 00:05:30 +0000203 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000204 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
205 bool isImmOpnd);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000206
207 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
208 SmallVectorImpl<MCInst> &Instructions);
209
Zoran Jovanoviccdb64562015-09-28 11:11:34 +0000210 bool expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
211 SmallVectorImpl<MCInst> &Instructions);
212
Toma Tabacue1e460d2015-06-11 10:36:10 +0000213 bool expandBranchImm(MCInst &Inst, SMLoc IDLoc,
214 SmallVectorImpl<MCInst> &Instructions);
215
Toma Tabacu1a108322015-06-17 13:20:24 +0000216 bool expandCondBranches(MCInst &Inst, SMLoc IDLoc,
217 SmallVectorImpl<MCInst> &Instructions);
218
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000219 bool expandDiv(MCInst &Inst, SMLoc IDLoc,
220 SmallVectorImpl<MCInst> &Instructions, const bool IsMips64,
221 const bool Signed);
222
Zoran Jovanovicd665a662016-02-22 16:00:23 +0000223 bool expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU, SMLoc IDLoc,
224 SmallVectorImpl<MCInst> &Instructions);
225
Daniel Sanders6394ee52015-10-15 14:52:58 +0000226 bool expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
227 SmallVectorImpl<MCInst> &Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000228
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +0000229 bool expandUlw(MCInst &Inst, SMLoc IDLoc,
230 SmallVectorImpl<MCInst> &Instructions);
231
Zoran Jovanovic00f998b2015-11-19 14:15:03 +0000232 bool expandRotation(MCInst &Inst, SMLoc IDLoc,
233 SmallVectorImpl<MCInst> &Instructions);
234 bool expandRotationImm(MCInst &Inst, SMLoc IDLoc,
235 SmallVectorImpl<MCInst> &Instructions);
236 bool expandDRotation(MCInst &Inst, SMLoc IDLoc,
237 SmallVectorImpl<MCInst> &Instructions);
238 bool expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
239 SmallVectorImpl<MCInst> &Instructions);
240
Zoran Jovanovicd474ef32016-01-29 16:18:34 +0000241 bool expandAbs(MCInst &Inst, SMLoc IDLoc,
242 SmallVectorImpl<MCInst> &Instructions);
243
Toma Tabacu234482a2015-03-16 12:03:39 +0000244 void createNop(bool hasShortDelaySlot, SMLoc IDLoc,
245 SmallVectorImpl<MCInst> &Instructions);
246
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000247 void createAddu(unsigned DstReg, unsigned SrcReg, unsigned TrgReg,
Toma Tabacu0b3e9782015-06-23 14:00:54 +0000248 bool Is64Bit, SmallVectorImpl<MCInst> &Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000249
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000250 void createCpRestoreMemOp(bool IsLoad, int StackOffset, SMLoc IDLoc,
251 SmallVectorImpl<MCInst> &Instructions);
252
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000253 bool reportParseError(Twine ErrorMsg);
254 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000255
Jack Carterb5cf5902013-04-17 00:18:04 +0000256 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000257 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000258
Vladimir Medic4c299852013-11-06 11:27:05 +0000259 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000260
261 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000262 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000263 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000264 bool parseSetFeature(uint64_t Feature);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000265 bool isPicAndNotNxxAbi(); // Used by .cpload, .cprestore, and .cpsetup.
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000266 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000267 bool parseDirectiveCpRestore(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000268 bool parseDirectiveCPSetup();
Daniel Sandersf173dda2015-09-22 10:50:09 +0000269 bool parseDirectiveCPReturn();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000270 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000271 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000272 bool parseDirectiveOption();
Toma Tabacu9ca50962015-04-16 09:53:47 +0000273 bool parseInsnDirective();
Simon Atanasyanbe186202016-02-11 06:45:54 +0000274 bool parseSSectionDirective(StringRef Section, unsigned Type);
Jack Carter0b744b32012-10-04 02:29:46 +0000275
276 bool parseSetAtDirective();
277 bool parseSetNoAtDirective();
278 bool parseSetMacroDirective();
279 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000280 bool parseSetMsaDirective();
281 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000282 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000283 bool parseSetReorderDirective();
284 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000285 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000286 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000287 bool parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +0000288 bool parseSetOddSPRegDirective();
289 bool parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000290 bool parseSetPopDirective();
291 bool parseSetPushDirective();
Toma Tabacu29696502015-06-02 09:48:04 +0000292 bool parseSetSoftFloatDirective();
293 bool parseSetHardFloatDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000294
Jack Carterd76b2372013-03-21 21:44:16 +0000295 bool parseSetAssignment();
296
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000297 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000298 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000299 bool parseDirectiveGpDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000300 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000301 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000302 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
303 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000304
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000305 bool parseInternalDirectiveReallowModule();
306
Jack Carterdc1e35d2012-09-06 20:00:02 +0000307 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000308
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000309 bool eatComma(StringRef ErrorStr);
310
Jack Carter1ac53222013-02-20 23:11:17 +0000311 int matchCPURegisterName(StringRef Symbol);
312
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000313 int matchHWRegsRegisterName(StringRef Symbol);
314
Jack Carter873c7242013-01-12 01:03:14 +0000315 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000316
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000317 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000318
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000319 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000320
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000321 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000322
Jack Carter5dc8ac92013-09-25 23:50:44 +0000323 int matchMSA128RegisterName(StringRef Name);
324
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000325 int matchMSA128CtrlRegisterName(StringRef Name);
326
Jack Carterd0bd6422013-04-18 00:41:53 +0000327 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000328
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000329 unsigned getGPR(int RegNo);
330
Toma Tabacu89a712b2015-04-15 10:48:56 +0000331 /// Returns the internal register number for the current AT. Also checks if
332 /// the current AT is unavailable (set to $0) and gives an error if it is.
333 /// This should be used in pseudo-instruction expansions which need AT.
334 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000335
336 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000337 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000338
339 // Helper function that checks if the value of a vector index is within the
340 // boundaries of accepted values for each RegisterKind
341 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
342 bool validateMSAIndex(int Val, int RegKind);
343
Daniel Sandersf0df2212014-08-04 12:20:00 +0000344 // Selects a new architecture by updating the FeatureBits with the necessary
345 // info including implied dependencies.
346 // Internally, it clears all the feature bits related to *any* architecture
347 // and selects the new one using the ToggleFeature functionality of the
348 // MCSubtargetInfo object that handles implied dependencies. The reason we
349 // clear all the arch related bits manually is because ToggleFeature only
350 // clears the features that imply the feature being cleared and not the
351 // features implied by the feature being cleared. This is easier to see
352 // with an example:
353 // --------------------------------------------------
354 // | Feature | Implies |
355 // | -------------------------------------------------|
356 // | FeatureMips1 | None |
357 // | FeatureMips2 | FeatureMips1 |
358 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
359 // | FeatureMips4 | FeatureMips3 |
360 // | ... | |
361 // --------------------------------------------------
362 //
363 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
364 // FeatureMipsGP64 | FeatureMips1)
365 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
366 void selectArch(StringRef ArchFeature) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000367 MCSubtargetInfo &STI = copySTI();
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000368 FeatureBitset FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000369 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
370 STI.setFeatureBits(FeatureBits);
371 setAvailableFeatures(
372 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000373 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000374 }
375
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000376 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000377 if (!(getSTI().getFeatureBits()[Feature])) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000378 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000379 setAvailableFeatures(
380 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000381 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000382 }
383 }
384
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000385 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000386 if (getSTI().getFeatureBits()[Feature]) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000387 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000388 setAvailableFeatures(
389 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000390 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000391 }
392 }
393
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000394 void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
395 setFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000396 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000397 }
398
399 void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
400 clearFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000401 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000402 }
403
Rafael Espindola870c4e92012-01-11 03:56:41 +0000404public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000405 enum MipsMatchResultTy {
Daniel Sanders52da7af2015-11-06 12:11:03 +0000406 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY,
Matheus Almeida595fcab2014-06-11 15:05:56 +0000407#define GET_OPERAND_DIAGNOSTIC_TYPES
408#include "MipsGenAsmMatcher.inc"
409#undef GET_OPERAND_DIAGNOSTIC_TYPES
Matheus Almeida595fcab2014-06-11 15:05:56 +0000410 };
411
Akira Hatanakab11ef082015-11-14 06:35:56 +0000412 MipsAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000413 const MCInstrInfo &MII, const MCTargetOptions &Options)
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000414 : MCTargetAsmParser(Options, sti),
Daniel Sanders50f17232015-09-15 16:17:27 +0000415 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
416 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000417 MCAsmParserExtension::Initialize(parser);
418
Toma Tabacu11e14a92015-04-21 11:50:52 +0000419 parser.addAliasForDirective(".asciiz", ".asciz");
420
Jack Carterb4dbc172012-09-05 23:34:03 +0000421 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000422 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000423
Toma Tabacu9db22db2014-09-09 10:15:38 +0000424 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000425 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000426 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000427
Toma Tabacu9db22db2014-09-09 10:15:38 +0000428 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000429 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000430 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000431
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000432 getTargetStreamer().updateABIInfo(*this);
433
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000434 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000435 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000436
437 CurrentFn = nullptr;
Toma Tabacud88d79c2015-06-23 14:39:42 +0000438
Daniel Sandersa6994442015-08-18 12:33:54 +0000439 IsPicEnabled =
440 (getContext().getObjectFileInfo()->getRelocM() == Reloc::PIC_);
441
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000442 IsCpRestoreSet = false;
443 CpRestoreOffset = -1;
444
Daniel Sanders50f17232015-09-15 16:17:27 +0000445 Triple TheTriple(sti.getTargetTriple());
446 if ((TheTriple.getArch() == Triple::mips) ||
447 (TheTriple.getArch() == Triple::mips64))
Toma Tabacud88d79c2015-06-23 14:39:42 +0000448 IsLittleEndian = false;
449 else
450 IsLittleEndian = true;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000451 }
452
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000453 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
454 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
455
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000456 bool isGP64bit() const {
457 return getSTI().getFeatureBits()[Mips::FeatureGP64Bit];
458 }
459 bool isFP64bit() const {
460 return getSTI().getFeatureBits()[Mips::FeatureFP64Bit];
461 }
Eric Christophera5762812015-01-26 17:33:46 +0000462 const MipsABIInfo &getABI() const { return ABI; }
463 bool isABI_N32() const { return ABI.IsN32(); }
464 bool isABI_N64() const { return ABI.IsN64(); }
465 bool isABI_O32() const { return ABI.IsO32(); }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000466 bool isABI_FPXX() const {
467 return getSTI().getFeatureBits()[Mips::FeatureFPXX];
468 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000469
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000470 bool useOddSPReg() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000471 return !(getSTI().getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000472 }
473
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000474 bool inMicroMipsMode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000475 return getSTI().getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000476 }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000477 bool hasMips1() const {
478 return getSTI().getFeatureBits()[Mips::FeatureMips1];
479 }
480 bool hasMips2() const {
481 return getSTI().getFeatureBits()[Mips::FeatureMips2];
482 }
483 bool hasMips3() const {
484 return getSTI().getFeatureBits()[Mips::FeatureMips3];
485 }
486 bool hasMips4() const {
487 return getSTI().getFeatureBits()[Mips::FeatureMips4];
488 }
489 bool hasMips5() const {
490 return getSTI().getFeatureBits()[Mips::FeatureMips5];
491 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000492 bool hasMips32() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000493 return getSTI().getFeatureBits()[Mips::FeatureMips32];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000494 }
495 bool hasMips64() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000496 return getSTI().getFeatureBits()[Mips::FeatureMips64];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000497 }
498 bool hasMips32r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000499 return getSTI().getFeatureBits()[Mips::FeatureMips32r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000500 }
501 bool hasMips64r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000502 return getSTI().getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000503 }
Daniel Sanders17793142015-02-18 16:24:50 +0000504 bool hasMips32r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000505 return (getSTI().getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000506 }
507 bool hasMips64r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000508 return (getSTI().getFeatureBits()[Mips::FeatureMips64r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000509 }
510 bool hasMips32r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000511 return (getSTI().getFeatureBits()[Mips::FeatureMips32r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000512 }
513 bool hasMips64r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000514 return (getSTI().getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000515 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000516 bool hasMips32r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000517 return getSTI().getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000518 }
519 bool hasMips64r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000520 return getSTI().getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000521 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000522
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000523 bool hasDSP() const {
524 return getSTI().getFeatureBits()[Mips::FeatureDSP];
525 }
526 bool hasDSPR2() const {
527 return getSTI().getFeatureBits()[Mips::FeatureDSPR2];
528 }
529 bool hasDSPR3() const {
530 return getSTI().getFeatureBits()[Mips::FeatureDSPR3];
531 }
532 bool hasMSA() const {
533 return getSTI().getFeatureBits()[Mips::FeatureMSA];
534 }
Kai Nackee0245392015-01-27 19:11:28 +0000535 bool hasCnMips() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000536 return (getSTI().getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000537 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000538
Daniel Sandersa6994442015-08-18 12:33:54 +0000539 bool inPicMode() {
540 return IsPicEnabled;
541 }
542
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000543 bool inMips16Mode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000544 return getSTI().getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000545 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000546
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000547 bool useTraps() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000548 return getSTI().getFeatureBits()[Mips::FeatureUseTCCInDIV];
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000549 }
550
Eric Christophere8ae3e32015-05-07 23:10:21 +0000551 bool useSoftFloat() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000552 return getSTI().getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000553 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000554
Toma Tabacud9d344b2015-04-27 14:05:04 +0000555 /// Warn if RegIndex is the same as the current AT.
556 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000557
558 void warnIfNoMacro(SMLoc Loc);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000559
560 bool isLittle() const { return IsLittleEndian; }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000561};
562}
563
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000564namespace {
565
566/// MipsOperand - Instances of this class represent a parsed Mips machine
567/// instruction.
568class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000569public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000570 /// Broad categories of register classes
571 /// The exact class is finalized by the render method.
572 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000573 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000574 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000575 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000576 RegKind_FCC = 4, /// FCC
577 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
578 RegKind_MSACtrl = 16, /// MSA control registers
579 RegKind_COP2 = 32, /// COP2
580 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
581 /// context).
582 RegKind_CCR = 128, /// CCR
583 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000584 RegKind_COP3 = 512, /// COP3
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000585 RegKind_COP0 = 1024, /// COP0
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000586 /// Potentially any (e.g. $1)
587 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
588 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000589 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
Jack Carter873c7242013-01-12 01:03:14 +0000590 };
591
592private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000593 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000594 k_Immediate, /// An immediate (possibly involving symbol references)
595 k_Memory, /// Base + Offset Memory Address
596 k_PhysRegister, /// A physical register from the Mips namespace
597 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000598 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000599 k_RegList, /// A physical register list
600 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000601 } Kind;
602
David Blaikie960ea3f2014-06-08 16:18:35 +0000603public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000604 MipsOperand(KindTy K, MipsAsmParser &Parser)
605 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
606
David Blaikie960ea3f2014-06-08 16:18:35 +0000607private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000608 /// For diagnostics, and checking the assembler temporary
609 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000610
Eric Christopher8996c5d2013-03-15 00:42:55 +0000611 struct Token {
612 const char *Data;
613 unsigned Length;
614 };
615
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000616 struct PhysRegOp {
617 unsigned Num; /// Register Number
618 };
619
620 struct RegIdxOp {
621 unsigned Index; /// Index into the register class
622 RegKind Kind; /// Bitfield of the kinds it could possibly be
623 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000624 };
625
626 struct ImmOp {
627 const MCExpr *Val;
628 };
629
630 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000631 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000632 const MCExpr *Off;
633 };
634
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000635 struct RegListOp {
636 SmallVector<unsigned, 10> *List;
637 };
638
Jack Carterb4dbc172012-09-05 23:34:03 +0000639 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000640 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000641 struct PhysRegOp PhysReg;
642 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000643 struct ImmOp Imm;
644 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000645 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000646 };
647
648 SMLoc StartLoc, EndLoc;
649
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000650 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000651 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
652 const MCRegisterInfo *RegInfo,
653 SMLoc S, SMLoc E,
654 MipsAsmParser &Parser) {
655 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000656 Op->RegIdx.Index = Index;
657 Op->RegIdx.RegInfo = RegInfo;
658 Op->RegIdx.Kind = RegKind;
659 Op->StartLoc = S;
660 Op->EndLoc = E;
661 return Op;
662 }
663
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000664public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000665 /// Coerce the register to GPR32 and return the real register for the current
666 /// target.
667 unsigned getGPR32Reg() const {
668 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000669 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000670 unsigned ClassID = Mips::GPR32RegClassID;
671 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000672 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000673
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000674 /// Coerce the register to GPR32 and return the real register for the current
675 /// target.
676 unsigned getGPRMM16Reg() const {
677 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
678 unsigned ClassID = Mips::GPR32RegClassID;
679 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
680 }
681
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000682 /// Coerce the register to GPR64 and return the real register for the current
683 /// target.
684 unsigned getGPR64Reg() const {
685 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
686 unsigned ClassID = Mips::GPR64RegClassID;
687 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000688 }
689
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000690private:
691 /// Coerce the register to AFGR64 and return the real register for the current
692 /// target.
693 unsigned getAFGR64Reg() const {
694 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
695 if (RegIdx.Index % 2 != 0)
696 AsmParser.Warning(StartLoc, "Float register should be even.");
697 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
698 .getRegister(RegIdx.Index / 2);
699 }
700
701 /// Coerce the register to FGR64 and return the real register for the current
702 /// target.
703 unsigned getFGR64Reg() const {
704 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
705 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
706 .getRegister(RegIdx.Index);
707 }
708
709 /// Coerce the register to FGR32 and return the real register for the current
710 /// target.
711 unsigned getFGR32Reg() const {
712 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
713 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
714 .getRegister(RegIdx.Index);
715 }
716
717 /// Coerce the register to FGRH32 and return the real register for the current
718 /// target.
719 unsigned getFGRH32Reg() const {
720 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
721 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
722 .getRegister(RegIdx.Index);
723 }
724
725 /// Coerce the register to FCC and return the real register for the current
726 /// target.
727 unsigned getFCCReg() const {
728 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
729 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
730 .getRegister(RegIdx.Index);
731 }
732
733 /// Coerce the register to MSA128 and return the real register for the current
734 /// target.
735 unsigned getMSA128Reg() const {
736 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
737 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
738 // identical
739 unsigned ClassID = Mips::MSA128BRegClassID;
740 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
741 }
742
743 /// Coerce the register to MSACtrl and return the real register for the
744 /// current target.
745 unsigned getMSACtrlReg() const {
746 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
747 unsigned ClassID = Mips::MSACtrlRegClassID;
748 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
749 }
750
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000751 /// Coerce the register to COP0 and return the real register for the
752 /// current target.
753 unsigned getCOP0Reg() const {
754 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");
755 unsigned ClassID = Mips::COP0RegClassID;
756 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
757 }
758
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000759 /// Coerce the register to COP2 and return the real register for the
760 /// current target.
761 unsigned getCOP2Reg() const {
762 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
763 unsigned ClassID = Mips::COP2RegClassID;
764 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
765 }
766
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000767 /// Coerce the register to COP3 and return the real register for the
768 /// current target.
769 unsigned getCOP3Reg() const {
770 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
771 unsigned ClassID = Mips::COP3RegClassID;
772 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
773 }
774
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000775 /// Coerce the register to ACC64DSP and return the real register for the
776 /// current target.
777 unsigned getACC64DSPReg() const {
778 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
779 unsigned ClassID = Mips::ACC64DSPRegClassID;
780 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
781 }
782
783 /// Coerce the register to HI32DSP and return the real register for the
784 /// current target.
785 unsigned getHI32DSPReg() const {
786 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
787 unsigned ClassID = Mips::HI32DSPRegClassID;
788 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
789 }
790
791 /// Coerce the register to LO32DSP and return the real register for the
792 /// current target.
793 unsigned getLO32DSPReg() const {
794 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
795 unsigned ClassID = Mips::LO32DSPRegClassID;
796 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
797 }
798
799 /// Coerce the register to CCR and return the real register for the
800 /// current target.
801 unsigned getCCRReg() const {
802 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
803 unsigned ClassID = Mips::CCRRegClassID;
804 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
805 }
806
807 /// Coerce the register to HWRegs and return the real register for the
808 /// current target.
809 unsigned getHWRegsReg() const {
810 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
811 unsigned ClassID = Mips::HWRegsRegClassID;
812 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
813 }
814
815public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000816 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000817 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000818 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000819 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000820 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000821 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000822 else
Jim Grosbache9119e42015-05-13 18:37:00 +0000823 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000824 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000825
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000826 void addRegOperands(MCInst &Inst, unsigned N) const {
827 llvm_unreachable("Use a custom parser instead");
828 }
829
Daniel Sanders21bce302014-04-01 12:35:23 +0000830 /// Render the operand to an MCInst as a GPR32
831 /// Asserts if the wrong number of operands are requested, or the operand
832 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000833 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
834 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000835 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000836 }
837
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000838 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
839 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000840 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000841 }
842
Jozef Kolek1904fa22014-11-24 14:25:53 +0000843 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
844 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000845 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +0000846 }
847
Zoran Jovanovic41688672015-02-10 16:36:20 +0000848 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
849 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000850 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000851 }
852
Daniel Sanders21bce302014-04-01 12:35:23 +0000853 /// Render the operand to an MCInst as a GPR64
854 /// Asserts if the wrong number of operands are requested, or the operand
855 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000856 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
857 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000858 Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000859 }
860
861 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
862 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000863 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000864 }
865
866 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
867 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000868 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000869 }
870
871 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
872 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000873 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000874 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000875 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000876 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
877 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000878 }
879
880 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
881 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000882 Inst.addOperand(MCOperand::createReg(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000883 }
884
885 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
886 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000887 Inst.addOperand(MCOperand::createReg(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000888 }
889
890 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
891 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000892 Inst.addOperand(MCOperand::createReg(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000893 }
894
895 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
896 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000897 Inst.addOperand(MCOperand::createReg(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000898 }
899
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000900 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
901 assert(N == 1 && "Invalid number of operands!");
902 Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
903 }
904
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000905 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
906 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000907 Inst.addOperand(MCOperand::createReg(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000908 }
909
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000910 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
911 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000912 Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000913 }
914
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000915 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
916 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000917 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000918 }
919
920 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
921 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000922 Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000923 }
924
925 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
926 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000927 Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000928 }
929
930 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
931 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000932 Inst.addOperand(MCOperand::createReg(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000933 }
934
935 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
936 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000937 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000938 }
939
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +0000940 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
Daniel Sanders52da7af2015-11-06 12:11:03 +0000941 void addConstantUImmOperands(MCInst &Inst, unsigned N) const {
942 assert(N == 1 && "Invalid number of operands!");
Daniel Sandersea4f6532015-11-06 12:22:31 +0000943 uint64_t Imm = getConstantImm() - Offset;
944 Imm &= (1 << Bits) - 1;
945 Imm += Offset;
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +0000946 Imm += AdjustOffset;
Daniel Sanders52da7af2015-11-06 12:11:03 +0000947 Inst.addOperand(MCOperand::createImm(Imm));
948 }
949
Daniel Sandersf8bb23e2016-02-01 15:13:31 +0000950 template <unsigned Bits>
951 void addUImmOperands(MCInst &Inst, unsigned N) const {
952 if (isImm() && !isConstantImm()) {
953 addExpr(Inst, getImm());
954 return;
955 }
956 addConstantUImmOperands<Bits, 0, 0>(Inst, N);
957 }
958
Daniel Sanders78e89022016-03-11 11:37:50 +0000959 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
960 void addConstantSImmOperands(MCInst &Inst, unsigned N) const {
961 assert(N == 1 && "Invalid number of operands!");
962 int64_t Imm = getConstantImm() - Offset;
963 Imm = SignExtend64<Bits>(Imm);
964 Imm += Offset;
965 Imm += AdjustOffset;
966 Inst.addOperand(MCOperand::createImm(Imm));
967 }
968
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000969 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000970 assert(N == 1 && "Invalid number of operands!");
971 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000972 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000973 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000974
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000975 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000976 assert(N == 2 && "Invalid number of operands!");
977
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000978 Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
979 ? getMemBase()->getGPR64Reg()
980 : getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000981
982 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000983 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000984 }
985
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000986 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
987 assert(N == 2 && "Invalid number of operands!");
988
Jim Grosbache9119e42015-05-13 18:37:00 +0000989 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000990
991 const MCExpr *Expr = getMemOff();
992 addExpr(Inst, Expr);
993 }
994
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000995 void addRegListOperands(MCInst &Inst, unsigned N) const {
996 assert(N == 1 && "Invalid number of operands!");
997
998 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000999 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001000 }
1001
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001002 void addRegPairOperands(MCInst &Inst, unsigned N) const {
1003 assert(N == 2 && "Invalid number of operands!");
1004 unsigned RegNo = getRegPair();
Jim Grosbache9119e42015-05-13 18:37:00 +00001005 Inst.addOperand(MCOperand::createReg(RegNo++));
1006 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001007 }
1008
Zoran Jovanovic41688672015-02-10 16:36:20 +00001009 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
1010 assert(N == 2 && "Invalid number of operands!");
1011 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001012 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +00001013 }
1014
Craig Topper56c590a2014-04-29 07:58:02 +00001015 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001016 // As a special case until we sort out the definition of div/divu, pretend
1017 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
1018 if (isGPRAsmReg() && RegIdx.Index == 0)
1019 return true;
1020
1021 return Kind == k_PhysRegister;
1022 }
1023 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +00001024 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001025 bool isConstantImm() const {
Craig Topper66059c92015-11-18 07:07:59 +00001026 return isImm() && isa<MCConstantExpr>(getImm());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001027 }
Daniel Sanders52da7af2015-11-06 12:11:03 +00001028 bool isConstantImmz() const {
1029 return isConstantImm() && getConstantImm() == 0;
1030 }
Daniel Sandersea4f6532015-11-06 12:22:31 +00001031 template <unsigned Bits, int Offset = 0> bool isConstantUImm() const {
1032 return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset);
1033 }
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001034 template <unsigned Bits> bool isUImm() const {
1035 return isConstantImm() ? isUInt<Bits>(getConstantImm()) : isImm();
1036 }
1037 template <unsigned Bits> bool isAnyImm() const {
1038 return isConstantImm() ? (isInt<Bits>(getConstantImm()) ||
1039 isUInt<Bits>(getConstantImm()))
1040 : isImm();
1041 }
Daniel Sanders78e89022016-03-11 11:37:50 +00001042 template <unsigned Bits, int Offset = 0> bool isConstantSImm() const {
1043 return isConstantImm() && isInt<Bits>(getConstantImm() - Offset);
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +00001044 }
Hrvoje Varga46458d02016-02-25 12:53:29 +00001045 template <unsigned Bottom, unsigned Top> bool isConstantUImmRange() const {
1046 return isConstantImm() && getConstantImm() >= Bottom &&
1047 getConstantImm() <= Top;
1048 }
Craig Topper56c590a2014-04-29 07:58:02 +00001049 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001050 // Note: It's not possible to pretend that other operand kinds are tokens.
1051 // The matcher emitter checks tokens first.
1052 return Kind == k_Token;
1053 }
Craig Topper56c590a2014-04-29 07:58:02 +00001054 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001055 bool isConstantMemOff() const {
Craig Topper66059c92015-11-18 07:07:59 +00001056 return isMem() && isa<MCConstantExpr>(getMemOff());
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001057 }
1058 template <unsigned Bits> bool isMemWithSimmOffset() const {
Zoran Jovanovica6593ff2015-08-18 12:53:08 +00001059 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
1060 && getMemBase()->isGPRAsmReg();
1061 }
Zoran Jovanovic6e6a2c92015-09-16 09:14:35 +00001062 template <unsigned Bits> bool isMemWithSimmOffsetGPR() const {
1063 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff()) &&
1064 getMemBase()->isGPRAsmReg();
1065 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001066 bool isMemWithGRPMM16Base() const {
1067 return isMem() && getMemBase()->isMM16AsmReg();
1068 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001069 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
1070 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1071 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
1072 }
Jozef Kolek12c69822014-12-23 16:16:33 +00001073 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
1074 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1075 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1076 && (getMemBase()->getGPR32Reg() == Mips::SP);
1077 }
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001078 template <unsigned Bits, unsigned ShiftLeftAmount>
1079 bool isScaledUImm() const {
1080 return isConstantImm() &&
1081 isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm());
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00001082 }
Daniel Sanders97297772016-03-22 14:40:00 +00001083 template <unsigned Bits, unsigned ShiftLeftAmount>
1084 bool isScaledSImm() const {
1085 return isConstantImm() &&
1086 isShiftedInt<Bits, ShiftLeftAmount>(getConstantImm());
1087 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001088 bool isRegList16() const {
1089 if (!isRegList())
1090 return false;
1091
1092 int Size = RegList.List->size();
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001093 if (Size < 2 || Size > 5)
1094 return false;
1095
1096 unsigned R0 = RegList.List->front();
1097 unsigned R1 = RegList.List->back();
1098 if (!((R0 == Mips::S0 && R1 == Mips::RA) ||
1099 (R0 == Mips::S0_64 && R1 == Mips::RA_64)))
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001100 return false;
1101
1102 int PrevReg = *RegList.List->begin();
1103 for (int i = 1; i < Size - 1; i++) {
1104 int Reg = (*(RegList.List))[i];
1105 if ( Reg != PrevReg + 1)
1106 return false;
1107 PrevReg = Reg;
1108 }
1109
1110 return true;
1111 }
Vladimir Medic2b953d02013-10-01 09:48:56 +00001112 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001113 bool isLSAImm() const {
1114 if (!isConstantImm())
1115 return false;
1116 int64_t Val = getConstantImm();
1117 return 1 <= Val && Val <= 4;
1118 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001119 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001120 bool isMovePRegPair() const {
1121 if (Kind != k_RegList || RegList.List->size() != 2)
1122 return false;
1123
1124 unsigned R0 = RegList.List->front();
1125 unsigned R1 = RegList.List->back();
1126
1127 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
1128 (R0 == Mips::A1 && R1 == Mips::A3) ||
1129 (R0 == Mips::A2 && R1 == Mips::A3) ||
1130 (R0 == Mips::A0 && R1 == Mips::S5) ||
1131 (R0 == Mips::A0 && R1 == Mips::S6) ||
1132 (R0 == Mips::A0 && R1 == Mips::A1) ||
1133 (R0 == Mips::A0 && R1 == Mips::A2) ||
1134 (R0 == Mips::A0 && R1 == Mips::A3))
1135 return true;
1136
1137 return false;
1138 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001139
1140 StringRef getToken() const {
1141 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001142 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001143 }
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001144 bool isRegPair() const { return Kind == k_RegPair; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001145
Craig Topper56c590a2014-04-29 07:58:02 +00001146 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001147 // As a special case until we sort out the definition of div/divu, pretend
1148 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
1149 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1150 RegIdx.Kind & RegKind_GPR)
1151 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001152
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001153 assert(Kind == k_PhysRegister && "Invalid access!");
1154 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +00001155 }
1156
Jack Carterb4dbc172012-09-05 23:34:03 +00001157 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001158 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001159 return Imm.Val;
1160 }
1161
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001162 int64_t getConstantImm() const {
1163 const MCExpr *Val = getImm();
1164 return static_cast<const MCConstantExpr *>(Val)->getValue();
1165 }
1166
1167 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001168 assert((Kind == k_Memory) && "Invalid access!");
1169 return Mem.Base;
1170 }
1171
1172 const MCExpr *getMemOff() const {
1173 assert((Kind == k_Memory) && "Invalid access!");
1174 return Mem.Off;
1175 }
1176
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001177 int64_t getConstantMemOff() const {
1178 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1179 }
1180
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001181 const SmallVectorImpl<unsigned> &getRegList() const {
1182 assert((Kind == k_RegList) && "Invalid access!");
1183 return *(RegList.List);
1184 }
1185
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001186 unsigned getRegPair() const {
1187 assert((Kind == k_RegPair) && "Invalid access!");
1188 return RegIdx.Index;
1189 }
1190
David Blaikie960ea3f2014-06-08 16:18:35 +00001191 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1192 MipsAsmParser &Parser) {
1193 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001194 Op->Tok.Data = Str.data();
1195 Op->Tok.Length = Str.size();
1196 Op->StartLoc = S;
1197 Op->EndLoc = S;
1198 return Op;
1199 }
1200
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001201 /// Create a numeric register (e.g. $1). The exact register remains
1202 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001203 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001204 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001205 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001206 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001207 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001208 }
1209
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001210 /// Create a register that is definitely a GPR.
1211 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001212 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001213 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001214 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001215 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001216 }
1217
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001218 /// Create a register that is definitely a FGR.
1219 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001220 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001221 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001222 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001223 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
1224 }
1225
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001226 /// Create a register that is definitely a HWReg.
1227 /// This is typically only used for named registers such as $hwr_cpunum.
1228 static std::unique_ptr<MipsOperand>
1229 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
1230 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1231 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
1232 }
1233
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001234 /// Create a register that is definitely an FCC.
1235 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001236 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001237 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001238 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001239 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
1240 }
1241
1242 /// Create a register that is definitely an ACC.
1243 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001244 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001245 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001246 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001247 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
1248 }
1249
1250 /// Create a register that is definitely an MSA128.
1251 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001252 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001253 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001254 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001255 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
1256 }
1257
1258 /// Create a register that is definitely an MSACtrl.
1259 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001260 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001261 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001262 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001263 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
1264 }
1265
David Blaikie960ea3f2014-06-08 16:18:35 +00001266 static std::unique_ptr<MipsOperand>
1267 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1268 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001269 Op->Imm.Val = Val;
1270 Op->StartLoc = S;
1271 Op->EndLoc = E;
1272 return Op;
1273 }
1274
David Blaikie960ea3f2014-06-08 16:18:35 +00001275 static std::unique_ptr<MipsOperand>
1276 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1277 SMLoc E, MipsAsmParser &Parser) {
1278 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1279 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001280 Op->Mem.Off = Off;
1281 Op->StartLoc = S;
1282 Op->EndLoc = E;
1283 return Op;
1284 }
1285
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001286 static std::unique_ptr<MipsOperand>
1287 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1288 MipsAsmParser &Parser) {
1289 assert (Regs.size() > 0 && "Empty list not allowed");
1290
1291 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001292 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001293 Op->StartLoc = StartLoc;
1294 Op->EndLoc = EndLoc;
1295 return Op;
1296 }
1297
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001298 static std::unique_ptr<MipsOperand>
1299 CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1300 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
1301 Op->RegIdx.Index = RegNo;
1302 Op->StartLoc = S;
1303 Op->EndLoc = E;
1304 return Op;
1305 }
1306
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001307 bool isGPRAsmReg() const {
1308 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001309 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001310 bool isMM16AsmReg() const {
1311 if (!(isRegIdx() && RegIdx.Kind))
1312 return false;
1313 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1314 || RegIdx.Index == 16 || RegIdx.Index == 17);
1315 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001316 bool isMM16AsmRegZero() const {
1317 if (!(isRegIdx() && RegIdx.Kind))
1318 return false;
1319 return (RegIdx.Index == 0 ||
1320 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1321 RegIdx.Index == 17);
1322 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001323 bool isMM16AsmRegMoveP() const {
1324 if (!(isRegIdx() && RegIdx.Kind))
1325 return false;
1326 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1327 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1328 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001329 bool isFGRAsmReg() const {
1330 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1331 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001332 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001333 bool isHWRegsAsmReg() const {
1334 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001335 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001336 bool isCCRAsmReg() const {
1337 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001338 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001339 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001340 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1341 return false;
1342 if (!AsmParser.hasEightFccRegisters())
1343 return RegIdx.Index == 0;
1344 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001345 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001346 bool isACCAsmReg() const {
1347 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001348 }
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001349 bool isCOP0AsmReg() const {
1350 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1351 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001352 bool isCOP2AsmReg() const {
1353 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001354 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001355 bool isCOP3AsmReg() const {
1356 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1357 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001358 bool isMSA128AsmReg() const {
1359 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001360 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001361 bool isMSACtrlAsmReg() const {
1362 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001363 }
1364
Jack Carterb4dbc172012-09-05 23:34:03 +00001365 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001366 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001367 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001368 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001369
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001370 virtual ~MipsOperand() {
1371 switch (Kind) {
1372 case k_Immediate:
1373 break;
1374 case k_Memory:
1375 delete Mem.Base;
1376 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001377 case k_RegList:
1378 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001379 case k_PhysRegister:
1380 case k_RegisterIndex:
1381 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001382 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001383 break;
1384 }
1385 }
1386
Craig Topper56c590a2014-04-29 07:58:02 +00001387 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001388 switch (Kind) {
1389 case k_Immediate:
1390 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001391 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001392 OS << ">";
1393 break;
1394 case k_Memory:
1395 OS << "Mem<";
1396 Mem.Base->print(OS);
1397 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001398 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001399 OS << ">";
1400 break;
1401 case k_PhysRegister:
1402 OS << "PhysReg<" << PhysReg.Num << ">";
1403 break;
1404 case k_RegisterIndex:
1405 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1406 break;
1407 case k_Token:
1408 OS << Tok.Data;
1409 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001410 case k_RegList:
1411 OS << "RegList< ";
1412 for (auto Reg : (*RegList.List))
1413 OS << Reg << " ";
1414 OS << ">";
1415 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001416 case k_RegPair:
1417 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1418 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001419 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001420 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001421}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001422} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001423
Jack Carter9e65aa32013-03-22 00:05:30 +00001424namespace llvm {
1425extern const MCInstrDesc MipsInsts[];
1426}
1427static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1428 return MipsInsts[Opcode];
1429}
1430
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001431static bool hasShortDelaySlot(unsigned Opcode) {
1432 switch (Opcode) {
1433 case Mips::JALS_MM:
1434 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001435 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001436 case Mips::BGEZALS_MM:
1437 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001438 return true;
1439 default:
1440 return false;
1441 }
1442}
1443
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001444static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1445 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1446 return &SRExpr->getSymbol();
1447 }
1448
1449 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1450 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1451 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1452
1453 if (LHSSym)
1454 return LHSSym;
1455
1456 if (RHSSym)
1457 return RHSSym;
1458
1459 return nullptr;
1460 }
1461
1462 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1463 return getSingleMCSymbol(UExpr->getSubExpr());
1464
1465 return nullptr;
1466}
1467
1468static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1469 if (isa<MCSymbolRefExpr>(Expr))
1470 return 1;
1471
1472 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1473 return countMCSymbolRefExpr(BExpr->getLHS()) +
1474 countMCSymbolRefExpr(BExpr->getRHS());
1475
1476 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1477 return countMCSymbolRefExpr(UExpr->getSubExpr());
1478
1479 return 0;
1480}
1481
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001482namespace {
1483void emitRX(unsigned Opcode, unsigned Reg0, MCOperand Op1, SMLoc IDLoc,
1484 SmallVectorImpl<MCInst> &Instructions) {
1485 MCInst tmpInst;
1486 tmpInst.setOpcode(Opcode);
1487 tmpInst.addOperand(MCOperand::createReg(Reg0));
1488 tmpInst.addOperand(Op1);
1489 tmpInst.setLoc(IDLoc);
1490 Instructions.push_back(tmpInst);
1491}
1492
1493void emitRI(unsigned Opcode, unsigned Reg0, int32_t Imm, SMLoc IDLoc,
1494 SmallVectorImpl<MCInst> &Instructions) {
1495 emitRX(Opcode, Reg0, MCOperand::createImm(Imm), IDLoc, Instructions);
1496}
1497
1498void emitRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, SMLoc IDLoc,
1499 SmallVectorImpl<MCInst> &Instructions) {
1500 emitRX(Opcode, Reg0, MCOperand::createReg(Reg1), IDLoc, Instructions);
1501}
1502
1503void emitII(unsigned Opcode, int16_t Imm1, int16_t Imm2, SMLoc IDLoc,
1504 SmallVectorImpl<MCInst> &Instructions) {
1505 MCInst tmpInst;
1506 tmpInst.setOpcode(Opcode);
1507 tmpInst.addOperand(MCOperand::createImm(Imm1));
1508 tmpInst.addOperand(MCOperand::createImm(Imm2));
1509 tmpInst.setLoc(IDLoc);
1510 Instructions.push_back(tmpInst);
1511}
1512
1513void emitR(unsigned Opcode, unsigned Reg0, SMLoc IDLoc,
1514 SmallVectorImpl<MCInst> &Instructions) {
1515 MCInst tmpInst;
1516 tmpInst.setOpcode(Opcode);
1517 tmpInst.addOperand(MCOperand::createReg(Reg0));
1518 tmpInst.setLoc(IDLoc);
1519 Instructions.push_back(tmpInst);
1520}
1521
1522void emitRRX(unsigned Opcode, unsigned Reg0, unsigned Reg1, MCOperand Op2,
1523 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1524 MCInst tmpInst;
1525 tmpInst.setOpcode(Opcode);
1526 tmpInst.addOperand(MCOperand::createReg(Reg0));
1527 tmpInst.addOperand(MCOperand::createReg(Reg1));
1528 tmpInst.addOperand(Op2);
1529 tmpInst.setLoc(IDLoc);
1530 Instructions.push_back(tmpInst);
1531}
1532
1533void emitRRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, unsigned Reg2,
1534 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1535 emitRRX(Opcode, Reg0, Reg1, MCOperand::createReg(Reg2), IDLoc,
1536 Instructions);
1537}
1538
1539void emitRRI(unsigned Opcode, unsigned Reg0, unsigned Reg1, int16_t Imm,
1540 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1541 emitRRX(Opcode, Reg0, Reg1, MCOperand::createImm(Imm), IDLoc,
1542 Instructions);
1543}
1544
1545void emitAppropriateDSLL(unsigned DstReg, unsigned SrcReg, int16_t ShiftAmount,
1546 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1547 if (ShiftAmount >= 32) {
1548 emitRRI(Mips::DSLL32, DstReg, SrcReg, ShiftAmount - 32, IDLoc,
1549 Instructions);
1550 return;
1551 }
1552
1553 emitRRI(Mips::DSLL, DstReg, SrcReg, ShiftAmount, IDLoc, Instructions);
1554}
1555} // end anonymous namespace.
1556
Jack Carter9e65aa32013-03-22 00:05:30 +00001557bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001558 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001559 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001560 bool ExpandedJalSym = false;
Daniel Sandersa771fef2014-03-24 14:05:39 +00001561
Jack Carter9e65aa32013-03-22 00:05:30 +00001562 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001563
1564 if (MCID.isBranch() || MCID.isCall()) {
1565 const unsigned Opcode = Inst.getOpcode();
1566 MCOperand Offset;
1567
1568 switch (Opcode) {
1569 default:
1570 break;
Kai Nackee0245392015-01-27 19:11:28 +00001571 case Mips::BBIT0:
1572 case Mips::BBIT032:
1573 case Mips::BBIT1:
1574 case Mips::BBIT132:
1575 assert(hasCnMips() && "instruction only valid for octeon cpus");
1576 // Fall through
1577
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001578 case Mips::BEQ:
1579 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001580 case Mips::BEQ_MM:
1581 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001582 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001583 Offset = Inst.getOperand(2);
1584 if (!Offset.isImm())
1585 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001586 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001587 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001588 if (OffsetToAlignment(Offset.getImm(),
1589 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001590 return Error(IDLoc, "branch to misaligned address");
1591 break;
1592 case Mips::BGEZ:
1593 case Mips::BGTZ:
1594 case Mips::BLEZ:
1595 case Mips::BLTZ:
1596 case Mips::BGEZAL:
1597 case Mips::BLTZAL:
1598 case Mips::BC1F:
1599 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001600 case Mips::BGEZ_MM:
1601 case Mips::BGTZ_MM:
1602 case Mips::BLEZ_MM:
1603 case Mips::BLTZ_MM:
1604 case Mips::BGEZAL_MM:
1605 case Mips::BLTZAL_MM:
1606 case Mips::BC1F_MM:
1607 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001608 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001609 Offset = Inst.getOperand(1);
1610 if (!Offset.isImm())
1611 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001612 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001613 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001614 if (OffsetToAlignment(Offset.getImm(),
1615 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001616 return Error(IDLoc, "branch to misaligned address");
1617 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001618 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001619 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001620 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001621 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001622 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1623 Offset = Inst.getOperand(1);
1624 if (!Offset.isImm())
1625 break; // We'll deal with this situation later on when applying fixups.
Craig Topper55b1f292015-10-10 20:17:07 +00001626 if (!isInt<8>(Offset.getImm()))
Jozef Kolek9761e962015-01-12 12:03:34 +00001627 return Error(IDLoc, "branch target out of range");
1628 if (OffsetToAlignment(Offset.getImm(), 2LL))
1629 return Error(IDLoc, "branch to misaligned address");
1630 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001631 }
1632 }
1633
Daniel Sandersa84989a2014-06-16 13:25:35 +00001634 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1635 // We still accept it but it is a normal nop.
1636 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1637 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1638 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1639 "nop instruction");
1640 }
1641
Kai Nackee0245392015-01-27 19:11:28 +00001642 if (hasCnMips()) {
1643 const unsigned Opcode = Inst.getOpcode();
1644 MCOperand Opnd;
1645 int Imm;
1646
1647 switch (Opcode) {
1648 default:
1649 break;
1650
1651 case Mips::BBIT0:
1652 case Mips::BBIT032:
1653 case Mips::BBIT1:
1654 case Mips::BBIT132:
1655 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1656 // The offset is handled above
1657 Opnd = Inst.getOperand(1);
1658 if (!Opnd.isImm())
1659 return Error(IDLoc, "expected immediate operand kind");
1660 Imm = Opnd.getImm();
1661 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1662 Opcode == Mips::BBIT1 ? 63 : 31))
1663 return Error(IDLoc, "immediate operand value out of range");
1664 if (Imm > 31) {
1665 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1666 : Mips::BBIT132);
1667 Inst.getOperand(1).setImm(Imm - 32);
1668 }
1669 break;
1670
Kai Nackee0245392015-01-27 19:11:28 +00001671 case Mips::SEQi:
1672 case Mips::SNEi:
1673 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1674 Opnd = Inst.getOperand(2);
1675 if (!Opnd.isImm())
1676 return Error(IDLoc, "expected immediate operand kind");
1677 Imm = Opnd.getImm();
1678 if (!isInt<10>(Imm))
1679 return Error(IDLoc, "immediate operand value out of range");
1680 break;
1681 }
1682 }
1683
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001684 // This expansion is not in a function called by tryExpandInstruction()
1685 // because the pseudo-instruction doesn't have a distinct opcode.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001686 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
1687 inPicMode()) {
1688 warnIfNoMacro(IDLoc);
1689
1690 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
1691
1692 // We can do this expansion if there's only 1 symbol in the argument
1693 // expression.
1694 if (countMCSymbolRefExpr(JalExpr) > 1)
1695 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
1696
1697 // FIXME: This is checking the expression can be handled by the later stages
1698 // of the assembler. We ought to leave it to those later stages but
1699 // we can't do that until we stop evaluateRelocExpr() rewriting the
1700 // expressions into non-equivalent forms.
1701 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
1702
1703 // FIXME: Add support for label+offset operands (currently causes an error).
1704 // FIXME: Add support for forward-declared local symbols.
1705 // FIXME: Add expansion for when the LargeGOT option is enabled.
1706 if (JalSym->isInSection() || JalSym->isTemporary()) {
1707 if (isABI_O32()) {
1708 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001709 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001710 // R_(MICRO)MIPS_GOT16 label
1711 // addiu $25, $25, 0
1712 // R_(MICRO)MIPS_LO16 label
1713 // jalr $25
1714 const MCExpr *Got16RelocExpr = evaluateRelocExpr(JalExpr, "got");
1715 const MCExpr *Lo16RelocExpr = evaluateRelocExpr(JalExpr, "lo");
1716
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001717 emitRRX(Mips::LW, Mips::T9, Mips::GP,
1718 MCOperand::createExpr(Got16RelocExpr), IDLoc, Instructions);
1719 emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
1720 MCOperand::createExpr(Lo16RelocExpr), IDLoc, Instructions);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001721 } else if (isABI_N32() || isABI_N64()) {
1722 // If it's a local symbol and the N32/N64 ABIs are being used,
1723 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001724 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001725 // R_(MICRO)MIPS_GOT_DISP label
1726 // jalr $25
1727 const MCExpr *GotDispRelocExpr = evaluateRelocExpr(JalExpr, "got_disp");
1728
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001729 emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
1730 MCOperand::createExpr(GotDispRelocExpr), IDLoc, Instructions);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001731 }
1732 } else {
Daniel Sandersb7002032015-11-20 13:16:35 +00001733 // If it's an external/weak symbol, we expand to:
1734 // lw/ld $25, 0($gp)
1735 // R_(MICRO)MIPS_CALL16 label
1736 // jalr $25
1737 const MCExpr *Call16RelocExpr = evaluateRelocExpr(JalExpr, "call16");
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001738
Daniel Sandersb7002032015-11-20 13:16:35 +00001739 emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
1740 MCOperand::createExpr(Call16RelocExpr), IDLoc, Instructions);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001741 }
1742
1743 MCInst JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001744 if (IsCpRestoreSet && inMicroMipsMode())
1745 JalrInst.setOpcode(Mips::JALRS_MM);
1746 else
1747 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001748 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
1749 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
1750
1751 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
1752 // This relocation is supposed to be an optimization hint for the linker
1753 // and is not necessary for correctness.
1754
1755 Inst = JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001756 ExpandedJalSym = true;
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001757 }
1758
Jack Carter9e65aa32013-03-22 00:05:30 +00001759 if (MCID.mayLoad() || MCID.mayStore()) {
1760 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001761 // reference or immediate we may have to expand instructions.
1762 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001763 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001764 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1765 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001766 MCOperand &Op = Inst.getOperand(i);
1767 if (Op.isImm()) {
1768 int MemOffset = Op.getImm();
1769 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001770 // Offset can't exceed 16bit value.
1771 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001772 return false;
1773 }
1774 } else if (Op.isExpr()) {
1775 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001776 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001777 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001778 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001779 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001780 // Expand symbol.
1781 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001782 return false;
1783 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001784 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001785 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001786 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001787 }
1788 }
1789 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001790 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001791 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001792
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001793 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001794 if (MCID.mayLoad()) {
1795 // Try to create 16-bit GP relative load instruction.
1796 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1797 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1798 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1799 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1800 MCOperand &Op = Inst.getOperand(i);
1801 if (Op.isImm()) {
1802 int MemOffset = Op.getImm();
1803 MCOperand &DstReg = Inst.getOperand(0);
1804 MCOperand &BaseReg = Inst.getOperand(1);
Craig Topper55b1f292015-10-10 20:17:07 +00001805 if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&
Jozef Koleke10a02e2015-01-28 17:27:26 +00001806 getContext().getRegisterInfo()->getRegClass(
1807 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00001808 (BaseReg.getReg() == Mips::GP ||
1809 BaseReg.getReg() == Mips::GP_64)) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001810
1811 emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
1812 IDLoc, Instructions);
Jozef Koleke10a02e2015-01-28 17:27:26 +00001813 return false;
1814 }
1815 }
1816 }
1817 } // for
1818 } // if load
1819
1820 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1821
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001822 MCOperand Opnd;
1823 int Imm;
1824
1825 switch (Inst.getOpcode()) {
1826 default:
1827 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001828 case Mips::ADDIUSP_MM:
1829 Opnd = Inst.getOperand(0);
1830 if (!Opnd.isImm())
1831 return Error(IDLoc, "expected immediate operand kind");
1832 Imm = Opnd.getImm();
1833 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1834 Imm % 4 != 0)
1835 return Error(IDLoc, "immediate operand value out of range");
1836 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001837 case Mips::SLL16_MM:
1838 case Mips::SRL16_MM:
1839 Opnd = Inst.getOperand(2);
1840 if (!Opnd.isImm())
1841 return Error(IDLoc, "expected immediate operand kind");
1842 Imm = Opnd.getImm();
1843 if (Imm < 1 || Imm > 8)
1844 return Error(IDLoc, "immediate operand value out of range");
1845 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001846 case Mips::LI16_MM:
1847 Opnd = Inst.getOperand(1);
1848 if (!Opnd.isImm())
1849 return Error(IDLoc, "expected immediate operand kind");
1850 Imm = Opnd.getImm();
1851 if (Imm < -1 || Imm > 126)
1852 return Error(IDLoc, "immediate operand value out of range");
1853 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001854 case Mips::ADDIUR2_MM:
1855 Opnd = Inst.getOperand(2);
1856 if (!Opnd.isImm())
1857 return Error(IDLoc, "expected immediate operand kind");
1858 Imm = Opnd.getImm();
1859 if (!(Imm == 1 || Imm == -1 ||
1860 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1861 return Error(IDLoc, "immediate operand value out of range");
1862 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001863 case Mips::ANDI16_MM:
1864 Opnd = Inst.getOperand(2);
1865 if (!Opnd.isImm())
1866 return Error(IDLoc, "expected immediate operand kind");
1867 Imm = Opnd.getImm();
1868 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1869 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1870 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1871 return Error(IDLoc, "immediate operand value out of range");
1872 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001873 case Mips::LBU16_MM:
1874 Opnd = Inst.getOperand(2);
1875 if (!Opnd.isImm())
1876 return Error(IDLoc, "expected immediate operand kind");
1877 Imm = Opnd.getImm();
1878 if (Imm < -1 || Imm > 14)
1879 return Error(IDLoc, "immediate operand value out of range");
1880 break;
1881 case Mips::SB16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001882 case Mips::SB16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001883 Opnd = Inst.getOperand(2);
1884 if (!Opnd.isImm())
1885 return Error(IDLoc, "expected immediate operand kind");
1886 Imm = Opnd.getImm();
1887 if (Imm < 0 || Imm > 15)
1888 return Error(IDLoc, "immediate operand value out of range");
1889 break;
1890 case Mips::LHU16_MM:
1891 case Mips::SH16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001892 case Mips::SH16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001893 Opnd = Inst.getOperand(2);
1894 if (!Opnd.isImm())
1895 return Error(IDLoc, "expected immediate operand kind");
1896 Imm = Opnd.getImm();
1897 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1898 return Error(IDLoc, "immediate operand value out of range");
1899 break;
1900 case Mips::LW16_MM:
1901 case Mips::SW16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001902 case Mips::SW16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001903 Opnd = Inst.getOperand(2);
1904 if (!Opnd.isImm())
1905 return Error(IDLoc, "expected immediate operand kind");
1906 Imm = Opnd.getImm();
1907 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1908 return Error(IDLoc, "immediate operand value out of range");
1909 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001910 case Mips::ADDIUPC_MM:
1911 MCOperand Opnd = Inst.getOperand(1);
1912 if (!Opnd.isImm())
1913 return Error(IDLoc, "expected immediate operand kind");
1914 int Imm = Opnd.getImm();
Craig Topper55b1f292015-10-10 20:17:07 +00001915 if ((Imm % 4 != 0) || !isInt<25>(Imm))
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001916 return Error(IDLoc, "immediate operand value out of range");
1917 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001918 }
1919 }
1920
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001921 MacroExpanderResultTy ExpandResult =
1922 tryExpandInstruction(Inst, IDLoc, Instructions);
1923 switch (ExpandResult) {
1924 case MER_NotAMacro:
Jack Carter9e65aa32013-03-22 00:05:30 +00001925 Instructions.push_back(Inst);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001926 break;
1927 case MER_Success:
1928 break;
1929 case MER_Fail:
1930 return true;
1931 }
Jack Carter9e65aa32013-03-22 00:05:30 +00001932
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001933 // If this instruction has a delay slot and .set reorder is active,
1934 // emit a NOP after it.
1935 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
1936 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1937
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001938 if ((Inst.getOpcode() == Mips::JalOneReg ||
1939 Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
1940 isPicAndNotNxxAbi()) {
1941 if (IsCpRestoreSet) {
1942 // We need a NOP between the JALR and the LW:
1943 // If .set reorder has been used, we've already emitted a NOP.
1944 // If .set noreorder has been used, we need to emit a NOP at this point.
1945 if (!AssemblerOptions.back()->isReorder())
1946 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1947
1948 // Load the $gp from the stack.
1949 SmallVector<MCInst, 3> LoadInsts;
1950 createCpRestoreMemOp(true /*IsLoad*/, CpRestoreOffset /*StackOffset*/,
1951 IDLoc, LoadInsts);
1952
1953 for (const MCInst &Inst : LoadInsts)
1954 Instructions.push_back(Inst);
1955
1956 } else
1957 Warning(IDLoc, "no .cprestore used in PIC mode");
1958 }
1959
Jack Carter9e65aa32013-03-22 00:05:30 +00001960 return false;
1961}
1962
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001963MipsAsmParser::MacroExpanderResultTy
1964MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
1965 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001966 switch (Inst.getOpcode()) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001967 default:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001968 return MER_NotAMacro;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001969 case Mips::LoadImm32:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001970 return expandLoadImm(Inst, true, IDLoc, Instructions) ? MER_Fail
1971 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001972 case Mips::LoadImm64:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001973 return expandLoadImm(Inst, false, IDLoc, Instructions) ? MER_Fail
1974 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001975 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001976 case Mips::LoadAddrImm64:
1977 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1978 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
1979 "expected immediate operand kind");
1980
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001981 return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,
1982 Inst.getOperand(1),
1983 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,
1984 Instructions)
1985 ? MER_Fail
1986 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001987 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001988 case Mips::LoadAddrReg64:
1989 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1990 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1991 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
1992 "expected immediate operand kind");
1993
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001994 return expandLoadAddress(Inst.getOperand(0).getReg(),
1995 Inst.getOperand(1).getReg(), Inst.getOperand(2),
1996 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,
1997 Instructions)
1998 ? MER_Fail
1999 : MER_Success;
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002000 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00002001 case Mips::B_MMR6_Pseudo:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002002 return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions) ? MER_Fail
2003 : MER_Success;
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002004 case Mips::SWM_MM:
2005 case Mips::LWM_MM:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002006 return expandLoadStoreMultiple(Inst, IDLoc, Instructions) ? MER_Fail
2007 : MER_Success;
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002008 case Mips::JalOneReg:
2009 case Mips::JalTwoReg:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002010 return expandJalWithRegs(Inst, IDLoc, Instructions) ? MER_Fail
2011 : MER_Success;
Toma Tabacue1e460d2015-06-11 10:36:10 +00002012 case Mips::BneImm:
2013 case Mips::BeqImm:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002014 return expandBranchImm(Inst, IDLoc, Instructions) ? MER_Fail : MER_Success;
Toma Tabacu1a108322015-06-17 13:20:24 +00002015 case Mips::BLT:
2016 case Mips::BLE:
2017 case Mips::BGE:
2018 case Mips::BGT:
2019 case Mips::BLTU:
2020 case Mips::BLEU:
2021 case Mips::BGEU:
2022 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002023 case Mips::BLTL:
2024 case Mips::BLEL:
2025 case Mips::BGEL:
2026 case Mips::BGTL:
2027 case Mips::BLTUL:
2028 case Mips::BLEUL:
2029 case Mips::BGEUL:
2030 case Mips::BGTUL:
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002031 case Mips::BLTImmMacro:
2032 case Mips::BLEImmMacro:
2033 case Mips::BGEImmMacro:
2034 case Mips::BGTImmMacro:
2035 case Mips::BLTUImmMacro:
2036 case Mips::BLEUImmMacro:
2037 case Mips::BGEUImmMacro:
2038 case Mips::BGTUImmMacro:
2039 case Mips::BLTLImmMacro:
2040 case Mips::BLELImmMacro:
2041 case Mips::BGELImmMacro:
2042 case Mips::BGTLImmMacro:
2043 case Mips::BLTULImmMacro:
2044 case Mips::BLEULImmMacro:
2045 case Mips::BGEULImmMacro:
2046 case Mips::BGTULImmMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002047 return expandCondBranches(Inst, IDLoc, Instructions) ? MER_Fail
2048 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002049 case Mips::SDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002050 return expandDiv(Inst, IDLoc, Instructions, false, true) ? MER_Fail
2051 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002052 case Mips::DSDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002053 return expandDiv(Inst, IDLoc, Instructions, true, true) ? MER_Fail
2054 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002055 case Mips::UDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002056 return expandDiv(Inst, IDLoc, Instructions, false, false) ? MER_Fail
2057 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002058 case Mips::DUDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002059 return expandDiv(Inst, IDLoc, Instructions, true, false) ? MER_Fail
2060 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002061 case Mips::PseudoTRUNC_W_S:
2062 return expandTrunc(Inst, false, false, IDLoc, Instructions) ? MER_Fail
2063 : MER_Success;
2064 case Mips::PseudoTRUNC_W_D32:
2065 return expandTrunc(Inst, true, false, IDLoc, Instructions) ? MER_Fail
2066 : MER_Success;
2067 case Mips::PseudoTRUNC_W_D:
2068 return expandTrunc(Inst, true, true, IDLoc, Instructions) ? MER_Fail
2069 : MER_Success;
Daniel Sanders6394ee52015-10-15 14:52:58 +00002070 case Mips::Ulh:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002071 return expandUlh(Inst, true, IDLoc, Instructions) ? MER_Fail : MER_Success;
Toma Tabacud88d79c2015-06-23 14:39:42 +00002072 case Mips::Ulhu:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002073 return expandUlh(Inst, false, IDLoc, Instructions) ? MER_Fail : MER_Success;
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00002074 case Mips::Ulw:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002075 return expandUlw(Inst, IDLoc, Instructions) ? MER_Fail : MER_Success;
2076 case Mips::NORImm:
2077 return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail
2078 : MER_Success;
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002079 case Mips::ADDi:
2080 case Mips::ADDiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002081 case Mips::SLTi:
2082 case Mips::SLTiu:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002083 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2084 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2085 int64_t ImmValue = Inst.getOperand(2).getImm();
2086 if (isInt<16>(ImmValue))
2087 return MER_NotAMacro;
2088 return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail
2089 : MER_Success;
2090 }
2091 return MER_NotAMacro;
2092 case Mips::ANDi:
2093 case Mips::ORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002094 case Mips::XORi:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002095 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2096 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2097 int64_t ImmValue = Inst.getOperand(2).getImm();
2098 if (isUInt<16>(ImmValue))
2099 return MER_NotAMacro;
2100 return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail
2101 : MER_Success;
2102 }
2103 return MER_NotAMacro;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002104 case Mips::ROL:
2105 case Mips::ROR:
2106 return expandRotation(Inst, IDLoc, Instructions) ? MER_Fail
2107 : MER_Success;
2108 case Mips::ROLImm:
2109 case Mips::RORImm:
2110 return expandRotationImm(Inst, IDLoc, Instructions) ? MER_Fail
2111 : MER_Success;
2112 case Mips::DROL:
2113 case Mips::DROR:
2114 return expandDRotation(Inst, IDLoc, Instructions) ? MER_Fail
2115 : MER_Success;
2116 case Mips::DROLImm:
2117 case Mips::DRORImm:
2118 return expandDRotationImm(Inst, IDLoc, Instructions) ? MER_Fail
2119 : MER_Success;
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00002120 case Mips::ABSMacro:
2121 return expandAbs(Inst, IDLoc, Instructions) ? MER_Fail
2122 : MER_Success;
Jack Carterd0bd6422013-04-18 00:41:53 +00002123 }
Jack Carter30a59822012-10-04 04:03:53 +00002124}
Jack Carter92995f12012-10-06 00:53:28 +00002125
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002126bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
2127 SmallVectorImpl<MCInst> &Instructions) {
2128 // Create a JALR instruction which is going to replace the pseudo-JAL.
2129 MCInst JalrInst;
2130 JalrInst.setLoc(IDLoc);
2131 const MCOperand FirstRegOp = Inst.getOperand(0);
2132 const unsigned Opcode = Inst.getOpcode();
2133
2134 if (Opcode == Mips::JalOneReg) {
2135 // jal $rs => jalr $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002136 if (IsCpRestoreSet && inMicroMipsMode()) {
2137 JalrInst.setOpcode(Mips::JALRS16_MM);
2138 JalrInst.addOperand(FirstRegOp);
2139 } else if (inMicroMipsMode()) {
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002140 JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002141 JalrInst.addOperand(FirstRegOp);
2142 } else {
2143 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002144 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002145 JalrInst.addOperand(FirstRegOp);
2146 }
2147 } else if (Opcode == Mips::JalTwoReg) {
2148 // jal $rd, $rs => jalr $rd, $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002149 if (IsCpRestoreSet && inMicroMipsMode())
2150 JalrInst.setOpcode(Mips::JALRS_MM);
2151 else
2152 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002153 JalrInst.addOperand(FirstRegOp);
2154 const MCOperand SecondRegOp = Inst.getOperand(1);
2155 JalrInst.addOperand(SecondRegOp);
2156 }
2157 Instructions.push_back(JalrInst);
2158
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002159 // If .set reorder is active and branch instruction has a delay slot,
2160 // emit a NOP after it.
2161 const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
2162 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) {
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002163 createNop(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc, Instructions);
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002164 }
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002165
2166 return false;
2167}
2168
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002169/// Can the value be represented by a unsigned N-bit value and a shift left?
Benjamin Kramer039b1042015-10-28 13:54:36 +00002170template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002171 unsigned BitNum = findFirstSet(x);
2172
2173 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2174}
2175
2176/// Load (or add) an immediate into a register.
2177///
2178/// @param ImmValue The immediate to load.
2179/// @param DstReg The register that will hold the immediate.
2180/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2181/// for a simple initialization.
2182/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2183/// @param IsAddress True if the immediate represents an address. False if it
2184/// is an integer.
2185/// @param IDLoc Location of the immediate in the source file.
2186/// @param Instructions The instructions emitted by this expansion.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002187bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002188 unsigned SrcReg, bool Is32BitImm,
2189 bool IsAddress, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00002190 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu00e98672015-05-01 12:19:27 +00002191 if (!Is32BitImm && !isGP64bit()) {
2192 Error(IDLoc, "instruction requires a 64-bit architecture");
2193 return true;
2194 }
2195
Daniel Sanders03f9c012015-07-14 12:24:22 +00002196 if (Is32BitImm) {
2197 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2198 // Sign extend up to 64-bit so that the predicates match the hardware
2199 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2200 // true.
2201 ImmValue = SignExtend64<32>(ImmValue);
2202 } else {
2203 Error(IDLoc, "instruction requires a 32-bit immediate");
2204 return true;
2205 }
2206 }
2207
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002208 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2209 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2210
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002211 bool UseSrcReg = false;
2212 if (SrcReg != Mips::NoRegister)
2213 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002214
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002215 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002216 if (UseSrcReg &&
2217 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002218 // At this point we need AT to perform the expansions and we exit if it is
2219 // not available.
2220 unsigned ATReg = getATReg(IDLoc);
2221 if (!ATReg)
2222 return true;
2223 TmpReg = ATReg;
2224 }
2225
Daniel Sanders03f9c012015-07-14 12:24:22 +00002226 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002227 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002228 SrcReg = ZeroReg;
2229
2230 // This doesn't quite follow the usual ABI expectations for N32 but matches
2231 // traditional assembler behaviour. N32 would normally use addiu for both
2232 // integers and addresses.
2233 if (IsAddress && !Is32BitImm) {
2234 emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
2235 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002236 }
2237
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002238 emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
2239 return false;
2240 }
2241
2242 if (isUInt<16>(ImmValue)) {
2243 unsigned TmpReg = DstReg;
2244 if (SrcReg == DstReg) {
2245 TmpReg = getATReg(IDLoc);
2246 if (!TmpReg)
2247 return true;
2248 }
2249
2250 emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002251 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002252 emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2253 return false;
2254 }
2255
2256 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002257 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002258
Toma Tabacu79588102015-04-29 10:19:56 +00002259 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2260 uint16_t Bits15To0 = ImmValue & 0xffff;
2261
Toma Tabacua3d056f2015-05-15 09:42:11 +00002262 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002263 // Traditional behaviour seems to special case this particular value. It's
2264 // not clear why other masks are handled differently.
2265 if (ImmValue == 0xffffffff) {
Daniel Sandersf1ae3672015-08-18 09:55:57 +00002266 emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, Instructions);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002267 emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, Instructions);
2268 if (UseSrcReg)
2269 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2270 return false;
2271 }
2272
2273 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002274 // upper 32 bits.
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002275 emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002276 emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, Instructions);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002277 if (Bits15To0)
2278 emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
2279 if (UseSrcReg)
2280 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2281 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002282 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002283
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002284 emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, Instructions);
2285 if (Bits15To0)
2286 emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002287 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002288 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2289 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002290 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002291
2292 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2293 if (Is32BitImm) {
2294 Error(IDLoc, "instruction requires a 32-bit immediate");
2295 return true;
2296 }
2297
2298 // Traditionally, these immediates are shifted as little as possible and as
2299 // such we align the most significant bit to bit 15 of our temporary.
2300 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2301 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2302 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2303 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
2304 emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, Instructions);
2305 emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, Instructions);
2306
2307 if (UseSrcReg)
2308 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2309
2310 return false;
2311 }
2312
2313 warnIfNoMacro(IDLoc);
2314
2315 // The remaining case is packed with a sequence of dsll and ori with zeros
2316 // being omitted and any neighbouring dsll's being coalesced.
2317 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2318
2319 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2320 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
2321 IDLoc, Instructions))
2322 return false;
2323
2324 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2325 // skip it and defer the shift to the next chunk.
2326 unsigned ShiftCarriedForwards = 16;
2327 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2328 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2329
2330 if (ImmChunk != 0) {
2331 emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
2332 Instructions);
2333 emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, Instructions);
2334 ShiftCarriedForwards = 0;
2335 }
2336
2337 ShiftCarriedForwards += 16;
2338 }
2339 ShiftCarriedForwards -= 16;
2340
2341 // Finish any remaining shifts left by trailing zeros.
2342 if (ShiftCarriedForwards)
2343 emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
2344 Instructions);
2345
2346 if (UseSrcReg)
2347 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2348
Matheus Almeida3813d572014-06-19 14:39:14 +00002349 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002350}
Jack Carter92995f12012-10-06 00:53:28 +00002351
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002352bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
2353 SmallVectorImpl<MCInst> &Instructions) {
2354 const MCOperand &ImmOp = Inst.getOperand(1);
2355 assert(ImmOp.isImm() && "expected immediate operand kind");
2356 const MCOperand &DstRegOp = Inst.getOperand(0);
2357 assert(DstRegOp.isReg() && "expected register operand kind");
2358
2359 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002360 Is32BitImm, false, IDLoc, Instructions))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002361 return true;
2362
2363 return false;
2364}
2365
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002366bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2367 const MCOperand &Offset,
2368 bool Is32BitAddress, SMLoc IDLoc,
2369 SmallVectorImpl<MCInst> &Instructions) {
2370 // la can't produce a usable address when addresses are 64-bit.
2371 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2372 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2373 // We currently can't do this because we depend on the equality
2374 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2375 Error(IDLoc, "la used to load 64-bit address");
2376 // Continue as if we had 'dla' instead.
2377 Is32BitAddress = false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002378 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002379
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002380 // dla requires 64-bit addresses.
Scott Egerton24557012016-01-21 15:11:01 +00002381 if (!Is32BitAddress && !hasMips3()) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002382 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002383 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002384 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002385
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002386 if (!Offset.isImm())
2387 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
2388 Is32BitAddress, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002389
Scott Egerton24557012016-01-21 15:11:01 +00002390 if (!ABI.ArePtrs64bit()) {
2391 // Continue as if we had 'la' whether we had 'la' or 'dla'.
2392 Is32BitAddress = true;
2393 }
2394
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002395 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
2396 IDLoc, Instructions);
Jack Carter543fdf82012-10-09 23:29:45 +00002397}
2398
Toma Tabacuf712ede2015-06-17 14:31:51 +00002399bool MipsAsmParser::loadAndAddSymbolAddress(
2400 const MCExpr *SymExpr, unsigned DstReg, unsigned SrcReg, bool Is32BitSym,
2401 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002402 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002403
Daniel Sandersd5a89412015-10-05 13:19:29 +00002404 const MCExpr *Symbol = cast<MCExpr>(SymExpr);
2405 const MipsMCExpr *HiExpr = MipsMCExpr::create(
2406 MCSymbolRefExpr::VK_Mips_ABS_HI, Symbol, getContext());
2407 const MipsMCExpr *LoExpr = MipsMCExpr::create(
2408 MCSymbolRefExpr::VK_Mips_ABS_LO, Symbol, getContext());
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002409
Toma Tabacufb9d1252015-06-22 12:08:39 +00002410 bool UseSrcReg = SrcReg != Mips::NoRegister;
2411
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002412 // This is the 64-bit symbol address expansion.
2413 if (ABI.ArePtrs64bit() && isGP64bit()) {
2414 // We always need AT for the 64-bit expansion.
2415 // If it is not available we exit.
2416 unsigned ATReg = getATReg(IDLoc);
2417 if (!ATReg)
2418 return true;
2419
Daniel Sandersd5a89412015-10-05 13:19:29 +00002420 const MipsMCExpr *HighestExpr = MipsMCExpr::create(
2421 MCSymbolRefExpr::VK_Mips_HIGHEST, Symbol, getContext());
2422 const MipsMCExpr *HigherExpr = MipsMCExpr::create(
2423 MCSymbolRefExpr::VK_Mips_HIGHER, Symbol, getContext());
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002424
Scott Egerton24557012016-01-21 15:11:01 +00002425 if (UseSrcReg &&
2426 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2427 SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002428 // If $rs is the same as $rd:
2429 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
2430 // daddiu $at, $at, %higher(sym)
2431 // dsll $at, $at, 16
2432 // daddiu $at, $at, %hi(sym)
2433 // dsll $at, $at, 16
2434 // daddiu $at, $at, %lo(sym)
2435 // daddu $rd, $at, $rd
2436 emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
2437 Instructions);
2438 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HigherExpr),
2439 IDLoc, Instructions);
2440 emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
2441 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
2442 Instructions);
2443 emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
2444 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
2445 Instructions);
2446 emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, Instructions);
2447
2448 return false;
2449 }
2450
2451 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2452 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
2453 // lui $at, %hi(sym)
2454 // daddiu $rd, $rd, %higher(sym)
2455 // daddiu $at, $at, %lo(sym)
2456 // dsll32 $rd, $rd, 0
2457 // daddu $rd, $rd, $at
2458 // (daddu $rd, $rd, $rs)
2459 emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
2460 Instructions);
2461 emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
2462 Instructions);
2463 emitRRX(Mips::DADDiu, DstReg, DstReg, MCOperand::createExpr(HigherExpr),
2464 IDLoc, Instructions);
2465 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
2466 Instructions);
2467 emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, Instructions);
2468 emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, Instructions);
2469 if (UseSrcReg)
2470 emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, Instructions);
2471
2472 return false;
2473 }
2474
2475 // And now, the 32-bit symbol address expansion:
2476 // If $rs is the same as $rd:
2477 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
2478 // ori $at, $at, %lo(sym)
2479 // addu $rd, $at, $rd
2480 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2481 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
2482 // ori $rd, $rd, %lo(sym)
2483 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00002484 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002485 if (UseSrcReg &&
2486 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002487 // If $rs is the same as $rd, we need to use AT.
2488 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00002489 unsigned ATReg = getATReg(IDLoc);
2490 if (!ATReg)
2491 return true;
2492 TmpReg = ATReg;
2493 }
2494
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002495 emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, Instructions);
2496 emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr), IDLoc,
2497 Instructions);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002498
Toma Tabacufb9d1252015-06-22 12:08:39 +00002499 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002500 emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2501 else
Scott Egerton24557012016-01-21 15:11:01 +00002502 assert(
2503 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, TmpReg));
Toma Tabacuf712ede2015-06-17 14:31:51 +00002504
Toma Tabacu674825c2015-06-16 12:16:24 +00002505 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002506}
2507
NAKAMURA Takumi2bbc90c2015-01-23 01:02:07 +00002508bool MipsAsmParser::expandUncondBranchMMPseudo(
2509 MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00002510 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
2511 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002512
2513 MCOperand Offset = Inst.getOperand(0);
2514 if (Offset.isExpr()) {
2515 Inst.clear();
2516 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002517 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2518 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2519 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002520 } else {
2521 assert(Offset.isImm() && "expected immediate operand kind");
Craig Topper55b1f292015-10-10 20:17:07 +00002522 if (isInt<11>(Offset.getImm())) {
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002523 // If offset fits into 11 bits then this instruction becomes microMIPS
2524 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00002525 if (inMicroMipsMode())
2526 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002527 } else {
Craig Topper55b1f292015-10-10 20:17:07 +00002528 if (!isInt<17>(Offset.getImm()))
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002529 Error(IDLoc, "branch target out of range");
2530 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
2531 Error(IDLoc, "branch to misaligned address");
2532 Inst.clear();
2533 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002534 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2535 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2536 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002537 }
2538 }
2539 Instructions.push_back(Inst);
2540
Zoran Jovanovicada70912015-09-07 11:56:37 +00002541 // If .set reorder is active and branch instruction has a delay slot,
2542 // emit a NOP after it.
2543 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
2544 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Toma Tabacu234482a2015-03-16 12:03:39 +00002545 createNop(true, IDLoc, Instructions);
2546
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002547 return false;
2548}
2549
Toma Tabacue1e460d2015-06-11 10:36:10 +00002550bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc,
2551 SmallVectorImpl<MCInst> &Instructions) {
2552 const MCOperand &DstRegOp = Inst.getOperand(0);
2553 assert(DstRegOp.isReg() && "expected register operand kind");
2554
2555 const MCOperand &ImmOp = Inst.getOperand(1);
2556 assert(ImmOp.isImm() && "expected immediate operand kind");
2557
2558 const MCOperand &MemOffsetOp = Inst.getOperand(2);
Daniel Sanders90f0d0b2016-02-29 11:24:49 +00002559 assert((MemOffsetOp.isImm() || MemOffsetOp.isExpr()) &&
2560 "expected immediate or expression operand");
Toma Tabacue1e460d2015-06-11 10:36:10 +00002561
2562 unsigned OpCode = 0;
2563 switch(Inst.getOpcode()) {
2564 case Mips::BneImm:
2565 OpCode = Mips::BNE;
2566 break;
2567 case Mips::BeqImm:
2568 OpCode = Mips::BEQ;
2569 break;
2570 default:
2571 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
2572 break;
2573 }
2574
2575 int64_t ImmValue = ImmOp.getImm();
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002576 if (ImmValue == 0)
2577 emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
2578 Instructions);
2579 else {
Toma Tabacue1e460d2015-06-11 10:36:10 +00002580 warnIfNoMacro(IDLoc);
2581
2582 unsigned ATReg = getATReg(IDLoc);
2583 if (!ATReg)
2584 return true;
2585
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002586 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
2587 IDLoc, Instructions))
Toma Tabacue1e460d2015-06-11 10:36:10 +00002588 return true;
2589
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002590 emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, Instructions);
Toma Tabacue1e460d2015-06-11 10:36:10 +00002591 }
2592 return false;
2593}
2594
Jack Carter9e65aa32013-03-22 00:05:30 +00002595void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00002596 SmallVectorImpl<MCInst> &Instructions,
2597 bool isLoad, bool isImmOpnd) {
Scott Egertond65377d2016-03-17 10:37:51 +00002598 MCOperand HiOperand, LoOperand;
Jack Carter9e65aa32013-03-22 00:05:30 +00002599 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00002600 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002601 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2602 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002603 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002604 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2605 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002606 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00002607 if (isImmOpnd) {
2608 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
Scott Egertond65377d2016-03-17 10:37:51 +00002609 unsigned ImmOffset = Inst.getOperand(2).getImm();
2610 unsigned LoOffset = ImmOffset & 0x0000ffff;
2611 unsigned HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00002612 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00002613 if (LoOffset & 0x8000)
2614 HiOffset++;
Scott Egertond65377d2016-03-17 10:37:51 +00002615 LoOperand = MCOperand::createImm(LoOffset);
2616 HiOperand = MCOperand::createImm(HiOffset);
2617 } else {
2618 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
2619 LoOperand = MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "lo"));
2620 HiOperand = MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "hi"));
2621 }
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002622 // These are some of the types of expansions we perform here:
2623 // 1) lw $8, sym => lui $8, %hi(sym)
2624 // lw $8, %lo(sym)($8)
2625 // 2) lw $8, offset($9) => lui $8, %hi(offset)
2626 // add $8, $8, $9
2627 // lw $8, %lo(offset)($9)
2628 // 3) lw $8, offset($8) => lui $at, %hi(offset)
2629 // add $at, $at, $8
2630 // lw $8, %lo(offset)($at)
2631 // 4) sw $8, sym => lui $at, %hi(sym)
2632 // sw $8, %lo(sym)($at)
2633 // 5) sw $8, offset($8) => lui $at, %hi(offset)
2634 // add $at, $at, $8
2635 // sw $8, %lo(offset)($at)
2636 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
2637 // ldc1 $f0, %lo(sym)($at)
2638 //
2639 // For load instructions we can use the destination register as a temporary
2640 // if base and dst are different (examples 1 and 2) and if the base register
2641 // is general purpose otherwise we must use $at (example 6) and error if it's
2642 // not available. For stores we must use $at (examples 4 and 5) because we
2643 // must not clobber the source register setting up the offset.
2644 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
2645 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
2646 unsigned RegClassIDOp0 =
2647 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
2648 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
2649 (RegClassIDOp0 == Mips::GPR64RegClassID);
2650 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00002651 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002652 else {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002653 // At this point we need AT to perform the expansions and we exit if it is
2654 // not available.
Toma Tabacu89a712b2015-04-15 10:48:56 +00002655 TmpRegNum = getATReg(IDLoc);
2656 if (!TmpRegNum)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002657 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002658 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002659
Scott Egertond65377d2016-03-17 10:37:51 +00002660 emitRX(Mips::LUi, TmpRegNum, HiOperand, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00002661 // Add temp register to base.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002662 if (BaseRegNum != Mips::ZERO)
2663 emitRRR(Mips::ADDu, TmpRegNum, TmpRegNum, BaseRegNum, IDLoc, Instructions);
Alp Tokercb402912014-01-24 17:20:08 +00002664 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00002665 // of offset and new base.
Scott Egertond65377d2016-03-17 10:37:51 +00002666 emitRRX(Inst.getOpcode(), RegOpNum, TmpRegNum, LoOperand, IDLoc, Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +00002667}
2668
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002669bool
2670MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2671 SmallVectorImpl<MCInst> &Instructions) {
2672 unsigned OpNum = Inst.getNumOperands();
2673 unsigned Opcode = Inst.getOpcode();
2674 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2675
2676 assert (Inst.getOperand(OpNum - 1).isImm() &&
2677 Inst.getOperand(OpNum - 2).isReg() &&
2678 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2679
2680 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2681 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002682 (Inst.getOperand(OpNum - 2).getReg() == Mips::SP ||
2683 Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) &&
2684 (Inst.getOperand(OpNum - 3).getReg() == Mips::RA ||
2685 Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002686 // It can be implemented as SWM16 or LWM16 instruction.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002687 if (inMicroMipsMode() && hasMips32r6())
2688 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6;
2689 else
2690 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2691 }
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002692
2693 Inst.setOpcode(NewOpcode);
2694 Instructions.push_back(Inst);
2695 return false;
2696}
2697
Toma Tabacu1a108322015-06-17 13:20:24 +00002698bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
2699 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002700 bool EmittedNoMacroWarning = false;
Toma Tabacu1a108322015-06-17 13:20:24 +00002701 unsigned PseudoOpcode = Inst.getOpcode();
2702 unsigned SrcReg = Inst.getOperand(0).getReg();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002703 const MCOperand &TrgOp = Inst.getOperand(1);
Toma Tabacu1a108322015-06-17 13:20:24 +00002704 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
2705
2706 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002707 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00002708
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002709 unsigned TrgReg;
2710 if (TrgOp.isReg())
2711 TrgReg = TrgOp.getReg();
2712 else if (TrgOp.isImm()) {
2713 warnIfNoMacro(IDLoc);
2714 EmittedNoMacroWarning = true;
2715
2716 TrgReg = getATReg(IDLoc);
2717 if (!TrgReg)
2718 return true;
2719
2720 switch(PseudoOpcode) {
2721 default:
2722 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2723 case Mips::BLTImmMacro:
2724 PseudoOpcode = Mips::BLT;
2725 break;
2726 case Mips::BLEImmMacro:
2727 PseudoOpcode = Mips::BLE;
2728 break;
2729 case Mips::BGEImmMacro:
2730 PseudoOpcode = Mips::BGE;
2731 break;
2732 case Mips::BGTImmMacro:
2733 PseudoOpcode = Mips::BGT;
2734 break;
2735 case Mips::BLTUImmMacro:
2736 PseudoOpcode = Mips::BLTU;
2737 break;
2738 case Mips::BLEUImmMacro:
2739 PseudoOpcode = Mips::BLEU;
2740 break;
2741 case Mips::BGEUImmMacro:
2742 PseudoOpcode = Mips::BGEU;
2743 break;
2744 case Mips::BGTUImmMacro:
2745 PseudoOpcode = Mips::BGTU;
2746 break;
2747 case Mips::BLTLImmMacro:
2748 PseudoOpcode = Mips::BLTL;
2749 break;
2750 case Mips::BLELImmMacro:
2751 PseudoOpcode = Mips::BLEL;
2752 break;
2753 case Mips::BGELImmMacro:
2754 PseudoOpcode = Mips::BGEL;
2755 break;
2756 case Mips::BGTLImmMacro:
2757 PseudoOpcode = Mips::BGTL;
2758 break;
2759 case Mips::BLTULImmMacro:
2760 PseudoOpcode = Mips::BLTUL;
2761 break;
2762 case Mips::BLEULImmMacro:
2763 PseudoOpcode = Mips::BLEUL;
2764 break;
2765 case Mips::BGEULImmMacro:
2766 PseudoOpcode = Mips::BGEUL;
2767 break;
2768 case Mips::BGTULImmMacro:
2769 PseudoOpcode = Mips::BGTUL;
2770 break;
2771 }
2772
2773 if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
2774 false, IDLoc, Instructions))
2775 return true;
2776 }
2777
Toma Tabacu1a108322015-06-17 13:20:24 +00002778 switch (PseudoOpcode) {
2779 case Mips::BLT:
2780 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002781 case Mips::BLTL:
2782 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002783 AcceptsEquality = false;
2784 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002785 IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
2786 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002787 ZeroSrcOpcode = Mips::BGTZ;
2788 ZeroTrgOpcode = Mips::BLTZ;
2789 break;
2790 case Mips::BLE:
2791 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002792 case Mips::BLEL:
2793 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002794 AcceptsEquality = true;
2795 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002796 IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
2797 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002798 ZeroSrcOpcode = Mips::BGEZ;
2799 ZeroTrgOpcode = Mips::BLEZ;
2800 break;
2801 case Mips::BGE:
2802 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002803 case Mips::BGEL:
2804 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002805 AcceptsEquality = true;
2806 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002807 IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
2808 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002809 ZeroSrcOpcode = Mips::BLEZ;
2810 ZeroTrgOpcode = Mips::BGEZ;
2811 break;
2812 case Mips::BGT:
2813 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002814 case Mips::BGTL:
2815 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002816 AcceptsEquality = false;
2817 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002818 IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
2819 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002820 ZeroSrcOpcode = Mips::BLTZ;
2821 ZeroTrgOpcode = Mips::BGTZ;
2822 break;
2823 default:
2824 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2825 }
2826
Toma Tabacu1a108322015-06-17 13:20:24 +00002827 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
2828 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
2829 if (IsSrcRegZero && IsTrgRegZero) {
2830 // FIXME: All of these Opcode-specific if's are needed for compatibility
2831 // with GAS' behaviour. However, they may not generate the most efficient
2832 // code in some circumstances.
2833 if (PseudoOpcode == Mips::BLT) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002834 emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2835 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002836 return false;
2837 }
2838 if (PseudoOpcode == Mips::BLE) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002839 emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2840 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002841 Warning(IDLoc, "branch is always taken");
2842 return false;
2843 }
2844 if (PseudoOpcode == Mips::BGE) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002845 emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2846 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002847 Warning(IDLoc, "branch is always taken");
2848 return false;
2849 }
2850 if (PseudoOpcode == Mips::BGT) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002851 emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2852 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002853 return false;
2854 }
2855 if (PseudoOpcode == Mips::BGTU) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002856 emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
2857 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002858 return false;
2859 }
2860 if (AcceptsEquality) {
2861 // If both registers are $0 and the pseudo-branch accepts equality, it
2862 // will always be taken, so we emit an unconditional branch.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002863 emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
2864 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002865 Warning(IDLoc, "branch is always taken");
2866 return false;
2867 }
2868 // If both registers are $0 and the pseudo-branch does not accept
2869 // equality, it will never be taken, so we don't have to emit anything.
2870 return false;
2871 }
2872 if (IsSrcRegZero || IsTrgRegZero) {
2873 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
2874 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
2875 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
2876 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
2877 // the pseudo-branch will never be taken, so we don't emit anything.
2878 // This only applies to unsigned pseudo-branches.
2879 return false;
2880 }
2881 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
2882 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
2883 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
2884 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
2885 // the pseudo-branch will always be taken, so we emit an unconditional
2886 // branch.
2887 // This only applies to unsigned pseudo-branches.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002888 emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
2889 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002890 Warning(IDLoc, "branch is always taken");
2891 return false;
2892 }
2893 if (IsUnsigned) {
2894 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
2895 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
2896 // the pseudo-branch will be taken only when the non-zero register is
2897 // different from 0, so we emit a BNEZ.
2898 //
2899 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
2900 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
2901 // the pseudo-branch will be taken only when the non-zero register is
2902 // equal to 0, so we emit a BEQZ.
2903 //
2904 // Because only BLEU and BGEU branch on equality, we can use the
2905 // AcceptsEquality variable to decide when to emit the BEQZ.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002906 emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
2907 IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
2908 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002909 return false;
2910 }
2911 // If we have a signed pseudo-branch and one of the registers is $0,
2912 // we can use an appropriate compare-to-zero branch. We select which one
2913 // to use in the switch statement above.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002914 emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
2915 IsSrcRegZero ? TrgReg : SrcReg, MCOperand::createExpr(OffsetExpr),
2916 IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002917 return false;
2918 }
2919
2920 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
2921 // expansions. If it is not available, we return.
2922 unsigned ATRegNum = getATReg(IDLoc);
2923 if (!ATRegNum)
2924 return true;
2925
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002926 if (!EmittedNoMacroWarning)
2927 warnIfNoMacro(IDLoc);
Toma Tabacu1a108322015-06-17 13:20:24 +00002928
2929 // SLT fits well with 2 of our 4 pseudo-branches:
2930 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
2931 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
2932 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
2933 // This is accomplished by using a BNEZ with the result of the SLT.
2934 //
2935 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
2936 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
2937 // Because only BGE and BLE branch on equality, we can use the
2938 // AcceptsEquality variable to decide when to emit the BEQZ.
2939 // Note that the order of the SLT arguments doesn't change between
2940 // opposites.
2941 //
2942 // The same applies to the unsigned variants, except that SLTu is used
2943 // instead of SLT.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002944 emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
2945 ReverseOrderSLT ? TrgReg : SrcReg, ReverseOrderSLT ? SrcReg : TrgReg,
2946 IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002947
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002948 emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
2949 : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
2950 ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2951 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002952 return false;
2953}
2954
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002955bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc,
2956 SmallVectorImpl<MCInst> &Instructions,
2957 const bool IsMips64, const bool Signed) {
2958 if (hasMips32r6()) {
2959 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
2960 return false;
2961 }
2962
2963 warnIfNoMacro(IDLoc);
2964
2965 const MCOperand &RsRegOp = Inst.getOperand(0);
2966 assert(RsRegOp.isReg() && "expected register operand kind");
2967 unsigned RsReg = RsRegOp.getReg();
2968
2969 const MCOperand &RtRegOp = Inst.getOperand(1);
2970 assert(RtRegOp.isReg() && "expected register operand kind");
2971 unsigned RtReg = RtRegOp.getReg();
2972 unsigned DivOp;
2973 unsigned ZeroReg;
2974
2975 if (IsMips64) {
2976 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
2977 ZeroReg = Mips::ZERO_64;
2978 } else {
2979 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
2980 ZeroReg = Mips::ZERO;
2981 }
2982
2983 bool UseTraps = useTraps();
2984
2985 if (RsReg == Mips::ZERO || RsReg == Mips::ZERO_64) {
2986 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)
2987 Warning(IDLoc, "dividing zero by zero");
2988 if (IsMips64) {
2989 if (Signed && (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)) {
2990 if (UseTraps) {
2991 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2992 return false;
2993 }
2994
2995 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2996 return false;
2997 }
2998 } else {
2999 emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
3000 return false;
3001 }
3002 }
3003
3004 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
3005 Warning(IDLoc, "division by zero");
3006 if (Signed) {
3007 if (UseTraps) {
3008 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
3009 return false;
3010 }
3011
3012 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
3013 return false;
3014 }
3015 }
3016
3017 // FIXME: The values for these two BranchTarget variables may be different in
3018 // micromips. These magic numbers need to be removed.
3019 unsigned BranchTargetNoTraps;
3020 unsigned BranchTarget;
3021
3022 if (UseTraps) {
3023 BranchTarget = IsMips64 ? 12 : 8;
3024 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
3025 } else {
3026 BranchTarget = IsMips64 ? 20 : 16;
3027 BranchTargetNoTraps = 8;
3028 // Branch to the li instruction.
3029 emitRRI(Mips::BNE, RtReg, ZeroReg, BranchTargetNoTraps, IDLoc,
3030 Instructions);
3031 }
3032
3033 emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
3034
3035 if (!UseTraps)
3036 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
3037
3038 if (!Signed) {
3039 emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
3040 return false;
3041 }
3042
3043 unsigned ATReg = getATReg(IDLoc);
3044 if (!ATReg)
3045 return true;
3046
3047 emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, Instructions);
3048 if (IsMips64) {
3049 // Branch to the mflo instruction.
3050 emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
3051 emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, Instructions);
3052 emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, Instructions);
3053 } else {
3054 // Branch to the mflo instruction.
3055 emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
3056 emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, Instructions);
3057 }
3058
3059 if (UseTraps)
3060 emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, Instructions);
3061 else {
3062 // Branch to the mflo instruction.
3063 emitRRI(Mips::BNE, RsReg, ATReg, BranchTargetNoTraps, IDLoc, Instructions);
3064 emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, Instructions);
3065 emitII(Mips::BREAK, 0x6, 0, IDLoc, Instructions);
3066 }
3067 emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
3068 return false;
3069}
3070
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003071bool MipsAsmParser::expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU,
3072 SMLoc IDLoc,
3073 SmallVectorImpl<MCInst> &Instructions) {
3074
3075 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
3076 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() &&
3077 Inst.getOperand(2).isReg() && "Invalid instruction operand.");
3078
3079 unsigned FirstReg = Inst.getOperand(0).getReg();
3080 unsigned SecondReg = Inst.getOperand(1).getReg();
3081 unsigned ThirdReg = Inst.getOperand(2).getReg();
3082
3083 if (hasMips1() && !hasMips2()) {
3084 unsigned ATReg = getATReg(IDLoc);
3085 if (!ATReg)
3086 return true;
3087 emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, Instructions);
3088 emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, Instructions);
3089 createNop(false, IDLoc, Instructions);
3090 emitRRI(Mips::ORi, ATReg, ThirdReg, 0x3, IDLoc, Instructions);
3091 emitRRI(Mips::XORi, ATReg, ATReg, 0x2, IDLoc, Instructions);
3092 emitRR(Mips::CTC1, Mips::RA, ATReg, IDLoc, Instructions);
3093 createNop(false, IDLoc, Instructions);
3094 emitRR(IsDouble ? (Is64FPU ? Mips::CVT_W_D64 : Mips::CVT_W_D32)
3095 : Mips::CVT_W_S,
3096 FirstReg, SecondReg, IDLoc, Instructions);
3097 emitRR(Mips::CTC1, Mips::RA, ThirdReg, IDLoc, Instructions);
3098 createNop(false, IDLoc, Instructions);
3099 return false;
3100 }
3101
3102 emitRR(IsDouble ? (Is64FPU ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32)
3103 : Mips::TRUNC_W_S,
3104 FirstReg, SecondReg, IDLoc, Instructions);
3105
3106 return false;
3107}
3108
Daniel Sanders6394ee52015-10-15 14:52:58 +00003109bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
3110 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacud88d79c2015-06-23 14:39:42 +00003111 if (hasMips32r6() || hasMips64r6()) {
3112 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3113 return false;
3114 }
3115
3116 warnIfNoMacro(IDLoc);
3117
3118 const MCOperand &DstRegOp = Inst.getOperand(0);
3119 assert(DstRegOp.isReg() && "expected register operand kind");
3120
3121 const MCOperand &SrcRegOp = Inst.getOperand(1);
3122 assert(SrcRegOp.isReg() && "expected register operand kind");
3123
3124 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3125 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3126
3127 unsigned DstReg = DstRegOp.getReg();
3128 unsigned SrcReg = SrcRegOp.getReg();
3129 int64_t OffsetValue = OffsetImmOp.getImm();
3130
3131 // NOTE: We always need AT for ULHU, as it is always used as the source
3132 // register for one of the LBu's.
3133 unsigned ATReg = getATReg(IDLoc);
3134 if (!ATReg)
3135 return true;
3136
3137 // When the value of offset+1 does not fit in 16 bits, we have to load the
3138 // offset in AT, (D)ADDu the original source register (if there was one), and
3139 // then use AT as the source register for the 2 generated LBu's.
3140 bool LoadedOffsetInAT = false;
3141 if (!isInt<16>(OffsetValue + 1) || !isInt<16>(OffsetValue)) {
3142 LoadedOffsetInAT = true;
3143
3144 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003145 true, IDLoc, Instructions))
Toma Tabacud88d79c2015-06-23 14:39:42 +00003146 return true;
3147
3148 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3149 // because it will make our output more similar to GAS'. For example,
3150 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3151 // instead of just an "ori $1, $9, 32768".
3152 // NOTE: If there is no source register specified in the ULHU, the parser
3153 // will interpret it as $0.
3154 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
3155 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
3156 }
3157
3158 unsigned FirstLbuDstReg = LoadedOffsetInAT ? DstReg : ATReg;
3159 unsigned SecondLbuDstReg = LoadedOffsetInAT ? ATReg : DstReg;
3160 unsigned LbuSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3161
3162 int64_t FirstLbuOffset = 0, SecondLbuOffset = 0;
3163 if (isLittle()) {
3164 FirstLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3165 SecondLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3166 } else {
3167 FirstLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3168 SecondLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3169 }
3170
3171 unsigned SllReg = LoadedOffsetInAT ? DstReg : ATReg;
3172
Daniel Sanders6394ee52015-10-15 14:52:58 +00003173 emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
3174 FirstLbuOffset, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003175
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003176 emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondLbuOffset, IDLoc,
3177 Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003178
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003179 emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003180
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003181 emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003182
3183 return false;
3184}
3185
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003186bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc,
3187 SmallVectorImpl<MCInst> &Instructions) {
3188 if (hasMips32r6() || hasMips64r6()) {
3189 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3190 return false;
3191 }
3192
3193 const MCOperand &DstRegOp = Inst.getOperand(0);
3194 assert(DstRegOp.isReg() && "expected register operand kind");
3195
3196 const MCOperand &SrcRegOp = Inst.getOperand(1);
3197 assert(SrcRegOp.isReg() && "expected register operand kind");
3198
3199 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3200 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3201
3202 unsigned SrcReg = SrcRegOp.getReg();
3203 int64_t OffsetValue = OffsetImmOp.getImm();
3204 unsigned ATReg = 0;
3205
3206 // When the value of offset+3 does not fit in 16 bits, we have to load the
3207 // offset in AT, (D)ADDu the original source register (if there was one), and
3208 // then use AT as the source register for the generated LWL and LWR.
3209 bool LoadedOffsetInAT = false;
3210 if (!isInt<16>(OffsetValue + 3) || !isInt<16>(OffsetValue)) {
3211 ATReg = getATReg(IDLoc);
3212 if (!ATReg)
3213 return true;
3214 LoadedOffsetInAT = true;
3215
3216 warnIfNoMacro(IDLoc);
3217
3218 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003219 true, IDLoc, Instructions))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003220 return true;
3221
3222 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3223 // because it will make our output more similar to GAS'. For example,
3224 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3225 // instead of just an "ori $1, $9, 32768".
3226 // NOTE: If there is no source register specified in the ULW, the parser
3227 // will interpret it as $0.
3228 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
3229 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
3230 }
3231
3232 unsigned FinalSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3233 int64_t LeftLoadOffset = 0, RightLoadOffset = 0;
3234 if (isLittle()) {
3235 LeftLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3236 RightLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3237 } else {
3238 LeftLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3239 RightLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3240 }
3241
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003242 emitRRI(Mips::LWL, DstRegOp.getReg(), FinalSrcReg, LeftLoadOffset, IDLoc,
3243 Instructions);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003244
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003245 emitRRI(Mips::LWR, DstRegOp.getReg(), FinalSrcReg, RightLoadOffset, IDLoc,
3246 Instructions);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003247
3248 return false;
3249}
3250
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003251bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
3252 SmallVectorImpl<MCInst> &Instructions) {
3253
3254 assert (Inst.getNumOperands() == 3 && "Invalid operand count");
3255 assert (Inst.getOperand(0).isReg() &&
3256 Inst.getOperand(1).isReg() &&
3257 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
3258
3259 unsigned ATReg = Mips::NoRegister;
3260 unsigned FinalDstReg = Mips::NoRegister;
3261 unsigned DstReg = Inst.getOperand(0).getReg();
3262 unsigned SrcReg = Inst.getOperand(1).getReg();
3263 int64_t ImmValue = Inst.getOperand(2).getImm();
3264
3265 bool Is32Bit = isInt<32>(ImmValue) || isUInt<32>(ImmValue);
3266
3267 unsigned FinalOpcode = Inst.getOpcode();
3268
3269 if (DstReg == SrcReg) {
3270 ATReg = getATReg(Inst.getLoc());
3271 if (!ATReg)
3272 return true;
3273 FinalDstReg = DstReg;
3274 DstReg = ATReg;
3275 }
3276
3277 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Instructions)) {
3278 switch (FinalOpcode) {
3279 default:
3280 llvm_unreachable("unimplemented expansion");
3281 case (Mips::ADDi):
3282 FinalOpcode = Mips::ADD;
3283 break;
3284 case (Mips::ADDiu):
3285 FinalOpcode = Mips::ADDu;
3286 break;
3287 case (Mips::ANDi):
3288 FinalOpcode = Mips::AND;
3289 break;
3290 case (Mips::NORImm):
3291 FinalOpcode = Mips::NOR;
3292 break;
3293 case (Mips::ORi):
3294 FinalOpcode = Mips::OR;
3295 break;
3296 case (Mips::SLTi):
3297 FinalOpcode = Mips::SLT;
3298 break;
3299 case (Mips::SLTiu):
3300 FinalOpcode = Mips::SLTu;
3301 break;
3302 case (Mips::XORi):
3303 FinalOpcode = Mips::XOR;
3304 break;
3305 }
3306
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003307 if (FinalDstReg == Mips::NoRegister)
3308 emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, Instructions);
3309 else
3310 emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc,
3311 Instructions);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003312 return false;
3313 }
3314 return true;
3315}
3316
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003317bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc,
3318 SmallVectorImpl<MCInst> &Instructions) {
3319 unsigned ATReg = Mips::NoRegister;
3320 unsigned DReg = Inst.getOperand(0).getReg();
3321 unsigned SReg = Inst.getOperand(1).getReg();
3322 unsigned TReg = Inst.getOperand(2).getReg();
3323 unsigned TmpReg = DReg;
3324
3325 unsigned FirstShift = Mips::NOP;
3326 unsigned SecondShift = Mips::NOP;
3327
3328 if (hasMips32r2()) {
3329
3330 if (DReg == SReg) {
3331 TmpReg = getATReg(Inst.getLoc());
3332 if (!TmpReg)
3333 return true;
3334 }
3335
3336 if (Inst.getOpcode() == Mips::ROL) {
3337 emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions);
3338 emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), Instructions);
3339 return false;
3340 }
3341
3342 if (Inst.getOpcode() == Mips::ROR) {
3343 emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), Instructions);
3344 return false;
3345 }
3346
3347 return true;
3348 }
3349
3350 if (hasMips32()) {
3351
3352 switch (Inst.getOpcode()) {
3353 default:
3354 llvm_unreachable("unexpected instruction opcode");
3355 case Mips::ROL:
3356 FirstShift = Mips::SRLV;
3357 SecondShift = Mips::SLLV;
3358 break;
3359 case Mips::ROR:
3360 FirstShift = Mips::SLLV;
3361 SecondShift = Mips::SRLV;
3362 break;
3363 }
3364
3365 ATReg = getATReg(Inst.getLoc());
3366 if (!ATReg)
3367 return true;
3368
3369 emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions);
3370 emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), Instructions);
3371 emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), Instructions);
3372 emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions);
3373
3374 return false;
3375 }
3376
3377 return true;
3378}
3379
3380bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
3381 SmallVectorImpl<MCInst> &Instructions) {
3382
3383 unsigned ATReg = Mips::NoRegister;
3384 unsigned DReg = Inst.getOperand(0).getReg();
3385 unsigned SReg = Inst.getOperand(1).getReg();
3386 int64_t ImmValue = Inst.getOperand(2).getImm();
3387
3388 unsigned FirstShift = Mips::NOP;
3389 unsigned SecondShift = Mips::NOP;
3390
3391 if (hasMips32r2()) {
3392
3393 if (Inst.getOpcode() == Mips::ROLImm) {
3394 uint64_t MaxShift = 32;
3395 uint64_t ShiftValue = ImmValue;
3396 if (ImmValue != 0)
3397 ShiftValue = MaxShift - ImmValue;
3398 emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), Instructions);
3399 return false;
3400 }
3401
3402 if (Inst.getOpcode() == Mips::RORImm) {
3403 emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), Instructions);
3404 return false;
3405 }
3406
3407 return true;
3408 }
3409
3410 if (hasMips32()) {
3411
3412 if (ImmValue == 0) {
3413 emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), Instructions);
3414 return false;
3415 }
3416
3417 switch (Inst.getOpcode()) {
3418 default:
3419 llvm_unreachable("unexpected instruction opcode");
3420 case Mips::ROLImm:
3421 FirstShift = Mips::SLL;
3422 SecondShift = Mips::SRL;
3423 break;
3424 case Mips::RORImm:
3425 FirstShift = Mips::SRL;
3426 SecondShift = Mips::SLL;
3427 break;
3428 }
3429
3430 ATReg = getATReg(Inst.getLoc());
3431 if (!ATReg)
3432 return true;
3433
3434 emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), Instructions);
3435 emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), Instructions);
3436 emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions);
3437
3438 return false;
3439 }
3440
3441 return true;
3442}
3443
3444bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc,
3445 SmallVectorImpl<MCInst> &Instructions) {
3446
3447 unsigned ATReg = Mips::NoRegister;
3448 unsigned DReg = Inst.getOperand(0).getReg();
3449 unsigned SReg = Inst.getOperand(1).getReg();
3450 unsigned TReg = Inst.getOperand(2).getReg();
3451 unsigned TmpReg = DReg;
3452
3453 unsigned FirstShift = Mips::NOP;
3454 unsigned SecondShift = Mips::NOP;
3455
3456 if (hasMips64r2()) {
3457
3458 if (TmpReg == SReg) {
3459 TmpReg = getATReg(Inst.getLoc());
3460 if (!TmpReg)
3461 return true;
3462 }
3463
3464 if (Inst.getOpcode() == Mips::DROL) {
3465 emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions);
3466 emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), Instructions);
3467 return false;
3468 }
3469
3470 if (Inst.getOpcode() == Mips::DROR) {
3471 emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), Instructions);
3472 return false;
3473 }
3474
3475 return true;
3476 }
3477
3478 if (hasMips64()) {
3479
3480 switch (Inst.getOpcode()) {
3481 default:
3482 llvm_unreachable("unexpected instruction opcode");
3483 case Mips::DROL:
3484 FirstShift = Mips::DSRLV;
3485 SecondShift = Mips::DSLLV;
3486 break;
3487 case Mips::DROR:
3488 FirstShift = Mips::DSLLV;
3489 SecondShift = Mips::DSRLV;
3490 break;
3491 }
3492
3493 ATReg = getATReg(Inst.getLoc());
3494 if (!ATReg)
3495 return true;
3496
3497 emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions);
3498 emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), Instructions);
3499 emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), Instructions);
3500 emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions);
3501
3502 return false;
3503 }
3504
3505 return true;
3506}
3507
3508bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
3509 SmallVectorImpl<MCInst> &Instructions) {
3510
3511 unsigned ATReg = Mips::NoRegister;
3512 unsigned DReg = Inst.getOperand(0).getReg();
3513 unsigned SReg = Inst.getOperand(1).getReg();
3514 int64_t ImmValue = Inst.getOperand(2).getImm() % 64;
3515
3516 unsigned FirstShift = Mips::NOP;
3517 unsigned SecondShift = Mips::NOP;
3518
3519 MCInst TmpInst;
3520
3521 if (hasMips64r2()) {
3522
3523 unsigned FinalOpcode = Mips::NOP;
3524 if (ImmValue == 0)
3525 FinalOpcode = Mips::DROTR;
3526 else if (ImmValue % 32 == 0)
3527 FinalOpcode = Mips::DROTR32;
3528 else if ((ImmValue >= 1) && (ImmValue <= 32)) {
3529 if (Inst.getOpcode() == Mips::DROLImm)
3530 FinalOpcode = Mips::DROTR32;
3531 else
3532 FinalOpcode = Mips::DROTR;
3533 } else if (ImmValue >= 33) {
3534 if (Inst.getOpcode() == Mips::DROLImm)
3535 FinalOpcode = Mips::DROTR;
3536 else
3537 FinalOpcode = Mips::DROTR32;
3538 }
3539
3540 uint64_t ShiftValue = ImmValue % 32;
3541 if (Inst.getOpcode() == Mips::DROLImm)
3542 ShiftValue = (32 - ImmValue % 32) % 32;
3543
3544 emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), Instructions);
3545
3546 return false;
3547 }
3548
3549 if (hasMips64()) {
3550
3551 if (ImmValue == 0) {
3552 emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), Instructions);
3553 return false;
3554 }
3555
3556 switch (Inst.getOpcode()) {
3557 default:
3558 llvm_unreachable("unexpected instruction opcode");
3559 case Mips::DROLImm:
3560 if ((ImmValue >= 1) && (ImmValue <= 31)) {
3561 FirstShift = Mips::DSLL;
3562 SecondShift = Mips::DSRL32;
3563 }
3564 if (ImmValue == 32) {
3565 FirstShift = Mips::DSLL32;
3566 SecondShift = Mips::DSRL32;
3567 }
3568 if ((ImmValue >= 33) && (ImmValue <= 63)) {
3569 FirstShift = Mips::DSLL32;
3570 SecondShift = Mips::DSRL;
3571 }
3572 break;
3573 case Mips::DRORImm:
3574 if ((ImmValue >= 1) && (ImmValue <= 31)) {
3575 FirstShift = Mips::DSRL;
3576 SecondShift = Mips::DSLL32;
3577 }
3578 if (ImmValue == 32) {
3579 FirstShift = Mips::DSRL32;
3580 SecondShift = Mips::DSLL32;
3581 }
3582 if ((ImmValue >= 33) && (ImmValue <= 63)) {
3583 FirstShift = Mips::DSRL32;
3584 SecondShift = Mips::DSLL;
3585 }
3586 break;
3587 }
3588
3589 ATReg = getATReg(Inst.getLoc());
3590 if (!ATReg)
3591 return true;
3592
3593 emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), Instructions);
3594 emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32, Inst.getLoc(), Instructions);
3595 emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions);
3596
3597 return false;
3598 }
3599
3600 return true;
3601}
3602
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003603bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc,
3604 SmallVectorImpl<MCInst> &Instructions) {
3605
3606 unsigned FirstRegOp = Inst.getOperand(0).getReg();
3607 unsigned SecondRegOp = Inst.getOperand(1).getReg();
3608
3609 emitRI(Mips::BGEZ, SecondRegOp, 8, IDLoc, Instructions);
3610 if (FirstRegOp != SecondRegOp)
3611 emitRRR(Mips::ADDu, FirstRegOp, SecondRegOp, Mips::ZERO, IDLoc, Instructions);
3612 else
3613 createNop(false, IDLoc, Instructions);
3614 emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, Instructions);
3615
3616 return false;
3617}
3618
Toma Tabacu234482a2015-03-16 12:03:39 +00003619void MipsAsmParser::createNop(bool hasShortDelaySlot, SMLoc IDLoc,
3620 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003621 if (hasShortDelaySlot)
3622 emitRR(Mips::MOVE16_MM, Mips::ZERO, Mips::ZERO, IDLoc, Instructions);
3623 else
3624 emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, Instructions);
Toma Tabacu234482a2015-03-16 12:03:39 +00003625}
3626
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003627void MipsAsmParser::createAddu(unsigned DstReg, unsigned SrcReg,
Toma Tabacu0b3e9782015-06-23 14:00:54 +00003628 unsigned TrgReg, bool Is64Bit,
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003629 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanders03f9c012015-07-14 12:24:22 +00003630 emitRRR(Is64Bit ? Mips::DADDu : Mips::ADDu, DstReg, SrcReg, TrgReg, SMLoc(),
3631 Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003632}
3633
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003634void MipsAsmParser::createCpRestoreMemOp(
3635 bool IsLoad, int StackOffset, SMLoc IDLoc,
3636 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003637 // If the offset can not fit into 16 bits, we need to expand.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003638 if (!isInt<16>(StackOffset)) {
3639 MCInst MemInst;
3640 MemInst.setOpcode(IsLoad ? Mips::LW : Mips::SW);
3641 MemInst.addOperand(MCOperand::createReg(Mips::GP));
3642 MemInst.addOperand(MCOperand::createReg(Mips::SP));
3643 MemInst.addOperand(MCOperand::createImm(StackOffset));
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003644 expandMemInst(MemInst, IDLoc, Instructions, IsLoad, true /*HasImmOpnd*/);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003645 return;
3646 }
3647
3648 emitRRI(IsLoad ? Mips::LW : Mips::SW, Mips::GP, Mips::SP, StackOffset, IDLoc,
3649 Instructions);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003650}
3651
Matheus Almeida595fcab2014-06-11 15:05:56 +00003652unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
3653 // As described by the Mips32r2 spec, the registers Rd and Rs for
3654 // jalr.hb must be different.
3655 unsigned Opcode = Inst.getOpcode();
3656
3657 if (Opcode == Mips::JALR_HB &&
3658 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
3659 return Match_RequiresDifferentSrcAndDst;
3660
3661 return Match_Success;
3662}
3663
Daniel Sanders52da7af2015-11-06 12:11:03 +00003664static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
3665 uint64_t ErrorInfo) {
3666 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
3667 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
3668 if (ErrorLoc == SMLoc())
3669 return Loc;
3670 return ErrorLoc;
3671 }
3672 return Loc;
3673}
3674
David Blaikie960ea3f2014-06-08 16:18:35 +00003675bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3676 OperandVector &Operands,
3677 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003678 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00003679 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00003680
Jack Carterb4dbc172012-09-05 23:34:03 +00003681 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00003682 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00003683 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003684 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00003685
3686 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003687 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003688 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00003689 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00003690 for (unsigned i = 0; i < Instructions.size(); i++)
Akira Hatanakabd9fc282015-11-14 05:20:05 +00003691 Out.EmitInstruction(Instructions[i], getSTI());
Jack Carterb4dbc172012-09-05 23:34:03 +00003692 return false;
3693 }
3694 case Match_MissingFeature:
3695 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
3696 return true;
3697 case Match_InvalidOperand: {
3698 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00003699 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003700 if (ErrorInfo >= Operands.size())
3701 return Error(IDLoc, "too few operands for instruction");
3702
Daniel Sanders52da7af2015-11-06 12:11:03 +00003703 ErrorLoc = Operands[ErrorInfo]->getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00003704 if (ErrorLoc == SMLoc())
3705 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00003706 }
3707
3708 return Error(ErrorLoc, "invalid operand for instruction");
3709 }
3710 case Match_MnemonicFail:
3711 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00003712 case Match_RequiresDifferentSrcAndDst:
3713 return Error(IDLoc, "source and destination must be different");
Daniel Sanders52da7af2015-11-06 12:11:03 +00003714 case Match_Immz:
3715 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00003716 case Match_UImm1_0:
3717 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3718 "expected 1-bit unsigned immediate");
Daniel Sandersea4f6532015-11-06 12:22:31 +00003719 case Match_UImm2_0:
3720 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3721 "expected 2-bit unsigned immediate");
3722 case Match_UImm2_1:
3723 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3724 "expected immediate in range 1 .. 4");
Daniel Sanders38ce0f62015-11-06 12:31:27 +00003725 case Match_UImm3_0:
3726 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3727 "expected 3-bit unsigned immediate");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00003728 case Match_UImm4_0:
3729 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3730 "expected 4-bit unsigned immediate");
Daniel Sanders78e89022016-03-11 11:37:50 +00003731 case Match_SImm4_0:
3732 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3733 "expected 4-bit signed immediate");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00003734 case Match_UImm5_0:
3735 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3736 "expected 5-bit unsigned immediate");
Daniel Sanders0f17d0d2016-03-22 14:29:53 +00003737 case Match_SImm5_0:
3738 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3739 "expected 5-bit signed immediate");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00003740 case Match_UImm5_1:
3741 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3742 "expected immediate in range 1 .. 32");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00003743 case Match_UImm5_32:
3744 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3745 "expected immediate in range 32 .. 63");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00003746 case Match_UImm5_33:
3747 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3748 "expected immediate in range 33 .. 64");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00003749 case Match_UImm5_0_Report_UImm6:
3750 // This is used on UImm5 operands that have a corresponding UImm5_32
3751 // operand to avoid confusing the user.
3752 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3753 "expected 6-bit unsigned immediate");
3754 case Match_UImm5_Lsl2:
3755 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3756 "expected both 7-bit unsigned immediate and multiple of 4");
Hrvoje Varga46458d02016-02-25 12:53:29 +00003757 case Match_UImmRange2_64:
3758 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3759 "expected immediate in range 2 .. 64");
Daniel Sanders59d092f2015-12-08 13:49:19 +00003760 case Match_UImm6_0:
3761 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3762 "expected 6-bit unsigned immediate");
Daniel Sanders19b7f762016-03-14 11:16:56 +00003763 case Match_UImm6_Lsl2:
3764 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3765 "expected both 8-bit unsigned immediate and multiple of 4");
Daniel Sanders78e89022016-03-11 11:37:50 +00003766 case Match_SImm6_0:
Zlatko Buljan252cca52015-12-18 08:59:37 +00003767 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3768 "expected 6-bit signed immediate");
3769 case Match_UImm7_0:
3770 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3771 "expected 7-bit unsigned immediate");
Daniel Sanders97297772016-03-22 14:40:00 +00003772 case Match_UImm7_N1:
3773 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3774 "expected immediate in range -1 .. 126");
3775 case Match_SImm7_Lsl2:
3776 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3777 "expected both 9-bit signed immediate and multiple of 4");
Daniel Sanders106d2d42015-12-08 14:42:10 +00003778 case Match_UImm8_0:
3779 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3780 "expected 8-bit unsigned immediate");
Daniel Sanders3c722312015-12-09 13:48:05 +00003781 case Match_UImm10_0:
3782 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3783 "expected 10-bit unsigned immediate");
Daniel Sanders837f1512016-03-24 13:26:59 +00003784 case Match_SImm10_0:
3785 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3786 "expected 10-bit signed immediate");
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00003787 case Match_UImm16:
3788 case Match_UImm16_Relaxed:
3789 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3790 "expected 16-bit unsigned immediate");
Daniel Sanders03a8d2f2016-02-29 16:06:38 +00003791 case Match_UImm20_0:
3792 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3793 "expected 20-bit unsigned immediate");
Daniel Sanders5d3840f2016-03-29 09:40:38 +00003794 case Match_UImm26_0:
3795 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3796 "expected 26-bit unsigned immediate");
Jack Carterb4dbc172012-09-05 23:34:03 +00003797 }
Craig Topper589ceee2015-01-03 08:16:34 +00003798
3799 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00003800}
3801
Toma Tabacud9d344b2015-04-27 14:05:04 +00003802void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
3803 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
3804 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
3805 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003806}
3807
Toma Tabacu81496c12015-05-20 08:54:45 +00003808void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
3809 if (!AssemblerOptions.back()->isMacro())
3810 Warning(Loc, "macro instruction expanded into multiple instructions");
3811}
3812
Daniel Sandersef638fe2014-10-03 15:37:37 +00003813void
3814MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
3815 SMRange Range, bool ShowColors) {
3816 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00003817 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00003818 ShowColors);
3819}
3820
Jack Carter1ac53222013-02-20 23:11:17 +00003821int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003822 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003823
Vladimir Medic4c299852013-11-06 11:27:05 +00003824 CC = StringSwitch<unsigned>(Name)
3825 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003826 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00003827 .Case("a0", 4)
3828 .Case("a1", 5)
3829 .Case("a2", 6)
3830 .Case("a3", 7)
3831 .Case("v0", 2)
3832 .Case("v1", 3)
3833 .Case("s0", 16)
3834 .Case("s1", 17)
3835 .Case("s2", 18)
3836 .Case("s3", 19)
3837 .Case("s4", 20)
3838 .Case("s5", 21)
3839 .Case("s6", 22)
3840 .Case("s7", 23)
3841 .Case("k0", 26)
3842 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003843 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00003844 .Case("sp", 29)
3845 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003846 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00003847 .Case("ra", 31)
3848 .Case("t0", 8)
3849 .Case("t1", 9)
3850 .Case("t2", 10)
3851 .Case("t3", 11)
3852 .Case("t4", 12)
3853 .Case("t5", 13)
3854 .Case("t6", 14)
3855 .Case("t7", 15)
3856 .Case("t8", 24)
3857 .Case("t9", 25)
3858 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003859
Toma Tabacufda445c2014-09-15 15:33:01 +00003860 if (!(isABI_N32() || isABI_N64()))
3861 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003862
Daniel Sandersef638fe2014-10-03 15:37:37 +00003863 if (12 <= CC && CC <= 15) {
3864 // Name is one of t4-t7
3865 AsmToken RegTok = getLexer().peekTok();
3866 SMRange RegRange = RegTok.getLocRange();
3867
3868 StringRef FixedName = StringSwitch<StringRef>(Name)
3869 .Case("t4", "t0")
3870 .Case("t5", "t1")
3871 .Case("t6", "t2")
3872 .Case("t7", "t3")
3873 .Default("");
3874 assert(FixedName != "" && "Register name is not one of t4-t7.");
3875
3876 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
3877 "Did you mean $" + FixedName + "?", RegRange);
3878 }
3879
Toma Tabacufda445c2014-09-15 15:33:01 +00003880 // Although SGI documentation just cuts out t0-t3 for n32/n64,
3881 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
3882 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
3883 if (8 <= CC && CC <= 11)
3884 CC += 4;
3885
3886 if (CC == -1)
3887 CC = StringSwitch<unsigned>(Name)
3888 .Case("a4", 8)
3889 .Case("a5", 9)
3890 .Case("a6", 10)
3891 .Case("a7", 11)
3892 .Case("kt0", 26)
3893 .Case("kt1", 27)
3894 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003895
3896 return CC;
3897}
Jack Carterd0bd6422013-04-18 00:41:53 +00003898
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003899int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
3900 int CC;
3901
3902 CC = StringSwitch<unsigned>(Name)
3903 .Case("hwr_cpunum", 0)
3904 .Case("hwr_synci_step", 1)
3905 .Case("hwr_cc", 2)
3906 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00003907 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003908 .Default(-1);
3909
3910 return CC;
3911}
3912
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003913int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003914
Jack Cartera63b16a2012-09-07 00:23:42 +00003915 if (Name[0] == 'f') {
3916 StringRef NumString = Name.substr(1);
3917 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003918 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003919 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003920 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00003921 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003922 return IntVal;
3923 }
3924 return -1;
3925}
Jack Cartera63b16a2012-09-07 00:23:42 +00003926
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003927int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
3928
3929 if (Name.startswith("fcc")) {
3930 StringRef NumString = Name.substr(3);
3931 unsigned IntVal;
3932 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003933 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003934 if (IntVal > 7) // There are only 8 fcc registers.
3935 return -1;
3936 return IntVal;
3937 }
3938 return -1;
3939}
3940
3941int MipsAsmParser::matchACRegisterName(StringRef Name) {
3942
Akira Hatanaka274d24c2013-08-14 01:15:52 +00003943 if (Name.startswith("ac")) {
3944 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003945 unsigned IntVal;
3946 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003947 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003948 if (IntVal > 3) // There are only 3 acc registers.
3949 return -1;
3950 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00003951 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003952 return -1;
3953}
Jack Carterd0bd6422013-04-18 00:41:53 +00003954
Jack Carter5dc8ac92013-09-25 23:50:44 +00003955int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
3956 unsigned IntVal;
3957
3958 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
3959 return -1;
3960
3961 if (IntVal > 31)
3962 return -1;
3963
3964 return IntVal;
3965}
3966
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003967int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
3968 int CC;
3969
3970 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00003971 .Case("msair", 0)
3972 .Case("msacsr", 1)
3973 .Case("msaaccess", 2)
3974 .Case("msasave", 3)
3975 .Case("msamodify", 4)
3976 .Case("msarequest", 5)
3977 .Case("msamap", 6)
3978 .Case("msaunmap", 7)
3979 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003980
3981 return CC;
3982}
3983
Toma Tabacu89a712b2015-04-15 10:48:56 +00003984unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00003985 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00003986 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00003987 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00003988 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00003989 return 0;
3990 }
3991 unsigned AT = getReg(
3992 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00003993 return AT;
3994}
Jack Carter0b744b32012-10-04 02:29:46 +00003995
Jack Carterd0bd6422013-04-18 00:41:53 +00003996unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00003997 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00003998}
3999
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004000unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004001 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00004002 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004003}
4004
Jack Carter873c7242013-01-12 01:03:14 +00004005int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004006 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00004007 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00004008 return -1;
4009
Jack Carter873c7242013-01-12 01:03:14 +00004010 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00004011}
4012
Toma Tabacu13964452014-09-04 13:23:44 +00004013bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004014 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004015 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004016
Jack Carter30a59822012-10-04 04:03:53 +00004017 // Check if the current operand has a custom associated parser, if so, try to
4018 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00004019 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4020 if (ResTy == MatchOperand_Success)
4021 return false;
4022 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4023 // there was a match, but an error occurred, in which case, just return that
4024 // the operand parsing failed.
4025 if (ResTy == MatchOperand_ParseFail)
4026 return true;
4027
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004028 DEBUG(dbgs() << ".. Generic Parser\n");
4029
Jack Carterb4dbc172012-09-05 23:34:03 +00004030 switch (getLexer().getKind()) {
4031 default:
4032 Error(Parser.getTok().getLoc(), "unexpected token in operand");
4033 return true;
4034 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00004035 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00004036 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00004037
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004038 // Almost all registers have been parsed by custom parsers. There is only
4039 // one exception to this. $zero (and it's alias $0) will reach this point
4040 // for div, divu, and similar instructions because it is not an operand
4041 // to the instruction definition but an explicit register. Special case
4042 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00004043 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00004044 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004045
Jack Carterd0bd6422013-04-18 00:41:53 +00004046 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00004047 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004048 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00004049 return true;
4050
Jack Carter873c7242013-01-12 01:03:14 +00004051 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00004052 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00004053 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00004054 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004055 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00004056
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004057 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004058 return false;
4059 }
Vladimir Medic4c299852013-11-06 11:27:05 +00004060 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00004061 case AsmToken::LParen:
4062 case AsmToken::Minus:
4063 case AsmToken::Plus:
4064 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00004065 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00004066 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004067 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00004068 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004069 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00004070 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00004071 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00004072 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004073 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00004074 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00004075 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00004076 return true;
4077
Jack Carter873c7242013-01-12 01:03:14 +00004078 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4079
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004080 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00004081 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004082 } // case AsmToken::Percent
4083 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00004084 return true;
4085}
4086
Vladimir Medic4c299852013-11-06 11:27:05 +00004087const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00004088 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00004089 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00004090 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00004091 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00004092 // It's a constant, evaluate reloc value.
4093 int16_t Val;
4094 switch (getVariantKind(RelocStr)) {
4095 case MCSymbolRefExpr::VK_Mips_ABS_LO:
4096 // Get the 1st 16-bits.
4097 Val = MCE->getValue() & 0xffff;
4098 break;
4099 case MCSymbolRefExpr::VK_Mips_ABS_HI:
Simon Atanasyan2fc1e3b2016-02-09 22:31:49 +00004100 case MCSymbolRefExpr::VK_Mips_GOT:
Sasa Stankovic06c47802014-04-03 10:37:45 +00004101 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
4102 // 16 bits being negative.
4103 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
4104 break;
4105 case MCSymbolRefExpr::VK_Mips_HIGHER:
4106 // Get the 3rd 16-bits.
4107 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
4108 break;
4109 case MCSymbolRefExpr::VK_Mips_HIGHEST:
4110 // Get the 4th 16-bits.
4111 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
4112 break;
4113 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00004114 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00004115 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00004116 return MCConstantExpr::create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00004117 }
4118
Jack Carterb5cf5902013-04-17 00:18:04 +00004119 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004120 // It's a symbol, create a symbolic expression from the symbol.
Toma Tabacu07c97b32015-06-17 10:43:45 +00004121 const MCSymbol *Symbol = &MSRE->getSymbol();
Jack Carterb5cf5902013-04-17 00:18:04 +00004122 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004123 Res = MCSymbolRefExpr::create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004124 return Res;
4125 }
4126
4127 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00004128 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
4129
Sasa Stankovic06c47802014-04-03 10:37:45 +00004130 // Try to create target expression.
4131 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
Jim Grosbach13760bd2015-05-30 01:25:56 +00004132 return MipsMCExpr::create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00004133
Jack Carterd0bd6422013-04-18 00:41:53 +00004134 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
4135 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004136 Res = MCBinaryExpr::create(BE->getOpcode(), LExp, RExp, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004137 return Res;
4138 }
4139
4140 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004141 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004142 Res = MCUnaryExpr::create(UN->getOpcode(), UnExp, getContext());
Jack Carterd0bd6422013-04-18 00:41:53 +00004143 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00004144 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004145 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00004146 return Expr;
4147}
4148
4149bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
4150
4151 switch (Expr->getKind()) {
4152 case MCExpr::Constant:
4153 return true;
4154 case MCExpr::SymbolRef:
4155 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
4156 case MCExpr::Binary:
4157 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
4158 if (!isEvaluated(BE->getLHS()))
4159 return false;
4160 return isEvaluated(BE->getRHS());
4161 }
4162 case MCExpr::Unary:
4163 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00004164 case MCExpr::Target:
4165 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004166 }
Jack Carterb5cf5902013-04-17 00:18:04 +00004167 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00004168}
Jack Carterd0bd6422013-04-18 00:41:53 +00004169
Jack Carterb5cf5902013-04-17 00:18:04 +00004170bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004171 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00004172 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00004173 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00004174 if (Tok.isNot(AsmToken::Identifier))
4175 return true;
4176
Yaron Keren075759a2015-03-30 15:42:36 +00004177 std::string Str = Tok.getIdentifier();
Jack Carterb5cf5902013-04-17 00:18:04 +00004178
Jack Carterd0bd6422013-04-18 00:41:53 +00004179 Parser.Lex(); // Eat the identifier.
4180 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004181 const MCExpr *IdVal;
4182 SMLoc EndLoc;
4183
4184 if (getLexer().getKind() == AsmToken::LParen) {
4185 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004186 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004187 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004188 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004189 const AsmToken &nextTok = Parser.getTok();
4190 if (nextTok.isNot(AsmToken::Identifier))
4191 return true;
4192 Str += "(%";
4193 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00004194 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00004195 if (getLexer().getKind() != AsmToken::LParen)
4196 return true;
4197 } else
4198 break;
4199 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004200 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00004201 return true;
4202
4203 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00004204 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004205
4206 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00004207 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004208
Jack Carterd0bd6422013-04-18 00:41:53 +00004209 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00004210 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004211}
4212
Jack Carterb4dbc172012-09-05 23:34:03 +00004213bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
4214 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004215 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00004216 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004217 if (ResTy == MatchOperand_Success) {
4218 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00004219 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004220 StartLoc = Operand.getStartLoc();
4221 EndLoc = Operand.getEndLoc();
4222
4223 // AFAIK, we only support numeric registers and named GPR's in CFI
4224 // directives.
4225 // Don't worry about eating tokens before failing. Using an unrecognised
4226 // register is a parse error.
4227 if (Operand.isGPRAsmReg()) {
4228 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004229 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004230 }
4231
4232 return (RegNo == (unsigned)-1);
4233 }
4234
4235 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00004236 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00004237}
4238
Jack Carterb5cf5902013-04-17 00:18:04 +00004239bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004240 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00004241 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00004242 bool Result = true;
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004243 unsigned NumOfLParen = 0;
Jack Carterb5cf5902013-04-17 00:18:04 +00004244
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004245 while (getLexer().getKind() == AsmToken::LParen) {
Jack Carterb5cf5902013-04-17 00:18:04 +00004246 Parser.Lex();
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004247 ++NumOfLParen;
4248 }
Jack Carter873c7242013-01-12 01:03:14 +00004249
Jack Carterd0bd6422013-04-18 00:41:53 +00004250 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00004251 default:
4252 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00004253 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00004254 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00004255 case AsmToken::Integer:
4256 case AsmToken::Minus:
4257 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00004258 if (isParenExpr)
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004259 Result = getParser().parseParenExprOfDepth(NumOfLParen, Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00004260 else
4261 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00004262 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00004263 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004264 break;
Jack Carter873c7242013-01-12 01:03:14 +00004265 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00004266 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00004267 }
Jack Carterb5cf5902013-04-17 00:18:04 +00004268 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004269}
4270
David Blaikie960ea3f2014-06-08 16:18:35 +00004271MipsAsmParser::OperandMatchResultTy
4272MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004273 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004274 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00004275 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00004276 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00004277 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004278 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00004279 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00004280 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00004281
Jack Carterb5cf5902013-04-17 00:18:04 +00004282 if (getLexer().getKind() == AsmToken::LParen) {
4283 Parser.Lex();
4284 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004285 }
4286
Jack Carterb5cf5902013-04-17 00:18:04 +00004287 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004288 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00004289 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004290
Jack Carterd0bd6422013-04-18 00:41:53 +00004291 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004292 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004293 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00004294 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00004295 SMLoc E =
4296 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004297 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00004298 return MatchOperand_Success;
4299 }
4300 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004301 SMLoc E =
4302 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00004303
Jack Carterd0bd6422013-04-18 00:41:53 +00004304 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004305 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00004306 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004307 S, E, *this);
4308 Operands.push_back(
4309 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00004310 return MatchOperand_Success;
4311 }
4312 Error(Parser.getTok().getLoc(), "'(' expected");
4313 return MatchOperand_ParseFail;
4314 }
4315
Jack Carterd0bd6422013-04-18 00:41:53 +00004316 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004317 }
4318
Toma Tabacu13964452014-09-04 13:23:44 +00004319 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004320 if (Res != MatchOperand_Success)
4321 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004322
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004323 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00004324 Error(Parser.getTok().getLoc(), "')' expected");
4325 return MatchOperand_ParseFail;
4326 }
4327
Jack Carter873c7242013-01-12 01:03:14 +00004328 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4329
Jack Carterd0bd6422013-04-18 00:41:53 +00004330 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004331
Craig Topper062a2ba2014-04-25 05:30:21 +00004332 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004333 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00004334
Jack Carterd0bd6422013-04-18 00:41:53 +00004335 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00004336 std::unique_ptr<MipsOperand> op(
4337 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00004338 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004339 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004340 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00004341 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004342 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
4343 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004344 if (IdVal->evaluateAsAbsolute(Imm))
4345 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004346 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004347 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00004348 getContext());
4349 }
4350
David Blaikie960ea3f2014-06-08 16:18:35 +00004351 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004352 return MatchOperand_Success;
4353}
4354
David Blaikie960ea3f2014-06-08 16:18:35 +00004355bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004356 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00004357 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00004358 if (Sym) {
4359 SMLoc S = Parser.getTok().getLoc();
4360 const MCExpr *Expr;
4361 if (Sym->isVariable())
4362 Expr = Sym->getVariableValue();
4363 else
4364 return false;
4365 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004366 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00004367 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00004368 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004369 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004370 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00004371 if (ResTy == MatchOperand_Success) {
4372 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00004373 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00004374 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004375 llvm_unreachable("Should never ParseFail");
4376 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00004377 }
4378 } else if (Expr->getKind() == MCExpr::Constant) {
4379 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00004380 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00004381 Operands.push_back(
4382 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00004383 return true;
4384 }
4385 }
4386 return false;
4387}
Jack Carterd0bd6422013-04-18 00:41:53 +00004388
Jack Carter873c7242013-01-12 01:03:14 +00004389MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004390MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00004391 StringRef Identifier,
4392 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004393 int Index = matchCPURegisterName(Identifier);
4394 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004395 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004396 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4397 return MatchOperand_Success;
4398 }
4399
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004400 Index = matchHWRegsRegisterName(Identifier);
4401 if (Index != -1) {
4402 Operands.push_back(MipsOperand::createHWRegsReg(
4403 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4404 return MatchOperand_Success;
4405 }
4406
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004407 Index = matchFPURegisterName(Identifier);
4408 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004409 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004410 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4411 return MatchOperand_Success;
4412 }
4413
4414 Index = matchFCCRegisterName(Identifier);
4415 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004416 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004417 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4418 return MatchOperand_Success;
4419 }
4420
4421 Index = matchACRegisterName(Identifier);
4422 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004423 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004424 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4425 return MatchOperand_Success;
4426 }
4427
4428 Index = matchMSA128RegisterName(Identifier);
4429 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004430 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004431 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4432 return MatchOperand_Success;
4433 }
4434
4435 Index = matchMSA128CtrlRegisterName(Identifier);
4436 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004437 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004438 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4439 return MatchOperand_Success;
4440 }
4441
4442 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00004443}
4444
4445MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004446MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004447 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00004448 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004449
4450 if (Token.is(AsmToken::Identifier)) {
4451 DEBUG(dbgs() << ".. identifier\n");
4452 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00004453 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004454 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00004455 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004456 } else if (Token.is(AsmToken::Integer)) {
4457 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00004458 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004459 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
4460 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004461 return MatchOperand_Success;
4462 }
4463
4464 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
4465
4466 return MatchOperand_NoMatch;
4467}
4468
David Blaikie960ea3f2014-06-08 16:18:35 +00004469MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004470MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004471 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004472 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004473
4474 auto Token = Parser.getTok();
4475
4476 SMLoc S = Token.getLoc();
4477
4478 if (Token.isNot(AsmToken::Dollar)) {
4479 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
4480 if (Token.is(AsmToken::Identifier)) {
4481 if (searchSymbolAlias(Operands))
4482 return MatchOperand_Success;
4483 }
4484 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
4485 return MatchOperand_NoMatch;
4486 }
4487 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004488
Toma Tabacu13964452014-09-04 13:23:44 +00004489 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00004490 if (ResTy == MatchOperand_Success) {
4491 Parser.Lex(); // $
4492 Parser.Lex(); // identifier
4493 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004494 return ResTy;
4495}
4496
4497MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004498MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004499 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004500 switch (getLexer().getKind()) {
4501 default:
4502 return MatchOperand_NoMatch;
4503 case AsmToken::LParen:
4504 case AsmToken::Minus:
4505 case AsmToken::Plus:
4506 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00004507 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004508 case AsmToken::String:
4509 break;
4510 }
4511
4512 const MCExpr *IdVal;
4513 SMLoc S = Parser.getTok().getLoc();
4514 if (getParser().parseExpression(IdVal))
4515 return MatchOperand_ParseFail;
4516
4517 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4518 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
4519 return MatchOperand_Success;
4520}
4521
David Blaikie960ea3f2014-06-08 16:18:35 +00004522MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004523MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004524 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004525 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004526
4527 SMLoc S = getLexer().getLoc();
4528
4529 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00004530 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004531 if (ResTy != MatchOperand_NoMatch)
4532 return ResTy;
4533
Daniel Sanders315386c2014-04-01 10:40:14 +00004534 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00004535 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00004536 if (ResTy != MatchOperand_NoMatch)
4537 return ResTy;
4538
Daniel Sandersffd84362014-04-01 10:41:48 +00004539 const MCExpr *Expr = nullptr;
4540 if (Parser.parseExpression(Expr)) {
4541 // We have no way of knowing if a symbol was consumed so we must ParseFail
4542 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004543 }
Daniel Sandersffd84362014-04-01 10:41:48 +00004544 Operands.push_back(
4545 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004546 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00004547}
4548
Vladimir Medic2b953d02013-10-01 09:48:56 +00004549MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00004550MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004551 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00004552 const MCExpr *IdVal;
4553 // If the first token is '$' we may have register operand.
4554 if (Parser.getTok().is(AsmToken::Dollar))
4555 return MatchOperand_NoMatch;
4556 SMLoc S = Parser.getTok().getLoc();
4557 if (getParser().parseExpression(IdVal))
4558 return MatchOperand_ParseFail;
4559 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00004560 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00004561 int64_t Val = MCE->getValue();
4562 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4563 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00004564 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00004565 return MatchOperand_Success;
4566}
4567
Matheus Almeida779c5932013-11-18 12:32:49 +00004568MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004569MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004570 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00004571 switch (getLexer().getKind()) {
4572 default:
4573 return MatchOperand_NoMatch;
4574 case AsmToken::LParen:
4575 case AsmToken::Plus:
4576 case AsmToken::Minus:
4577 case AsmToken::Integer:
4578 break;
4579 }
4580
4581 const MCExpr *Expr;
4582 SMLoc S = Parser.getTok().getLoc();
4583
4584 if (getParser().parseExpression(Expr))
4585 return MatchOperand_ParseFail;
4586
4587 int64_t Val;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004588 if (!Expr->evaluateAsAbsolute(Val)) {
Matheus Almeida779c5932013-11-18 12:32:49 +00004589 Error(S, "expected immediate value");
4590 return MatchOperand_ParseFail;
4591 }
4592
4593 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
4594 // and because the CPU always adds one to the immediate field, the allowed
4595 // range becomes 1..4. We'll only check the range here and will deal
4596 // with the addition/subtraction when actually decoding/encoding
4597 // the instruction.
4598 if (Val < 1 || Val > 4) {
4599 Error(S, "immediate not in range (1..4)");
4600 return MatchOperand_ParseFail;
4601 }
4602
Jack Carter3b2c96e2014-01-22 23:31:38 +00004603 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004604 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00004605 return MatchOperand_Success;
4606}
4607
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004608MipsAsmParser::OperandMatchResultTy
4609MipsAsmParser::parseRegisterList(OperandVector &Operands) {
4610 MCAsmParser &Parser = getParser();
4611 SmallVector<unsigned, 10> Regs;
4612 unsigned RegNo;
4613 unsigned PrevReg = Mips::NoRegister;
4614 bool RegRange = false;
4615 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4616
4617 if (Parser.getTok().isNot(AsmToken::Dollar))
4618 return MatchOperand_ParseFail;
4619
4620 SMLoc S = Parser.getTok().getLoc();
4621 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
4622 SMLoc E = getLexer().getLoc();
4623 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
4624 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
4625 if (RegRange) {
4626 // Remove last register operand because registers from register range
4627 // should be inserted first.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004628 if ((isGP64bit() && RegNo == Mips::RA_64) ||
4629 (!isGP64bit() && RegNo == Mips::RA)) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004630 Regs.push_back(RegNo);
4631 } else {
4632 unsigned TmpReg = PrevReg + 1;
4633 while (TmpReg <= RegNo) {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004634 if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) ||
4635 (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) &&
4636 isGP64bit())) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004637 Error(E, "invalid register operand");
4638 return MatchOperand_ParseFail;
4639 }
4640
4641 PrevReg = TmpReg;
4642 Regs.push_back(TmpReg++);
4643 }
4644 }
4645
4646 RegRange = false;
4647 } else {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004648 if ((PrevReg == Mips::NoRegister) &&
4649 ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) ||
4650 (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA)))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004651 Error(E, "$16 or $31 expected");
4652 return MatchOperand_ParseFail;
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004653 } else if (!(((RegNo == Mips::FP || RegNo == Mips::RA ||
4654 (RegNo >= Mips::S0 && RegNo <= Mips::S7)) &&
4655 !isGP64bit()) ||
4656 ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 ||
4657 (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) &&
4658 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004659 Error(E, "invalid register operand");
4660 return MatchOperand_ParseFail;
4661 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004662 ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) ||
4663 (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 &&
4664 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004665 Error(E, "consecutive register numbers expected");
4666 return MatchOperand_ParseFail;
4667 }
4668
4669 Regs.push_back(RegNo);
4670 }
4671
4672 if (Parser.getTok().is(AsmToken::Minus))
4673 RegRange = true;
4674
4675 if (!Parser.getTok().isNot(AsmToken::Minus) &&
4676 !Parser.getTok().isNot(AsmToken::Comma)) {
4677 Error(E, "',' or '-' expected");
4678 return MatchOperand_ParseFail;
4679 }
4680
4681 Lex(); // Consume comma or minus
4682 if (Parser.getTok().isNot(AsmToken::Dollar))
4683 break;
4684
4685 PrevReg = RegNo;
4686 }
4687
4688 SMLoc E = Parser.getTok().getLoc();
4689 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4690 parseMemOperand(Operands);
4691 return MatchOperand_Success;
4692}
4693
Zoran Jovanovic2deca342014-12-16 14:59:10 +00004694MipsAsmParser::OperandMatchResultTy
4695MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
4696 MCAsmParser &Parser = getParser();
4697
4698 SMLoc S = Parser.getTok().getLoc();
4699 if (parseAnyRegister(Operands) != MatchOperand_Success)
4700 return MatchOperand_ParseFail;
4701
4702 SMLoc E = Parser.getTok().getLoc();
4703 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
4704 unsigned Reg = Op.getGPR32Reg();
4705 Operands.pop_back();
4706 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
4707 return MatchOperand_Success;
4708}
4709
Zoran Jovanovic41688672015-02-10 16:36:20 +00004710MipsAsmParser::OperandMatchResultTy
4711MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
4712 MCAsmParser &Parser = getParser();
4713 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4714 SmallVector<unsigned, 10> Regs;
4715
4716 if (Parser.getTok().isNot(AsmToken::Dollar))
4717 return MatchOperand_ParseFail;
4718
4719 SMLoc S = Parser.getTok().getLoc();
4720
4721 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4722 return MatchOperand_ParseFail;
4723
4724 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4725 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4726 Regs.push_back(RegNo);
4727
4728 SMLoc E = Parser.getTok().getLoc();
4729 if (Parser.getTok().isNot(AsmToken::Comma)) {
4730 Error(E, "',' expected");
4731 return MatchOperand_ParseFail;
4732 }
4733
4734 // Remove comma.
4735 Parser.Lex();
4736
4737 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4738 return MatchOperand_ParseFail;
4739
4740 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4741 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4742 Regs.push_back(RegNo);
4743
4744 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4745
4746 return MatchOperand_Success;
4747}
4748
Jack Carterdc1e35d2012-09-06 20:00:02 +00004749MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
4750
Vladimir Medic4c299852013-11-06 11:27:05 +00004751 MCSymbolRefExpr::VariantKind VK =
4752 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
4753 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
4754 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
4755 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
4756 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
4757 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
4758 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
4759 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
4760 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
4761 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
4762 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
4763 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
4764 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
4765 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
4766 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
4767 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
4768 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
4769 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00004770 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
4771 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
4772 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
4773 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
4774 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
4775 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00004776 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
4777 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00004778 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00004779
Matheus Almeida2852af82014-04-22 10:15:54 +00004780 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00004781
Jack Carterdc1e35d2012-09-06 20:00:02 +00004782 return VK;
4783}
Jack Cartera63b16a2012-09-07 00:23:42 +00004784
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004785/// Sometimes (i.e. load/stores) the operand may be followed immediately by
4786/// either this.
4787/// ::= '(', register, ')'
4788/// handle it before we iterate so we don't get tripped up by the lack of
4789/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004790bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004791 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004792 if (getLexer().is(AsmToken::LParen)) {
4793 Operands.push_back(
4794 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
4795 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004796 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004797 SMLoc Loc = getLexer().getLoc();
4798 Parser.eatToEndOfStatement();
4799 return Error(Loc, "unexpected token in argument list");
4800 }
4801 if (Parser.getTok().isNot(AsmToken::RParen)) {
4802 SMLoc Loc = getLexer().getLoc();
4803 Parser.eatToEndOfStatement();
4804 return Error(Loc, "unexpected token, expected ')'");
4805 }
4806 Operands.push_back(
4807 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
4808 Parser.Lex();
4809 }
4810 return false;
4811}
4812
4813/// Sometimes (i.e. in MSA) the operand may be followed immediately by
4814/// either one of these.
4815/// ::= '[', register, ']'
4816/// ::= '[', integer, ']'
4817/// handle it before we iterate so we don't get tripped up by the lack of
4818/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004819bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00004820 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004821 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004822 if (getLexer().is(AsmToken::LBrac)) {
4823 Operands.push_back(
4824 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
4825 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004826 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004827 SMLoc Loc = getLexer().getLoc();
4828 Parser.eatToEndOfStatement();
4829 return Error(Loc, "unexpected token in argument list");
4830 }
4831 if (Parser.getTok().isNot(AsmToken::RBrac)) {
4832 SMLoc Loc = getLexer().getLoc();
4833 Parser.eatToEndOfStatement();
4834 return Error(Loc, "unexpected token, expected ']'");
4835 }
4836 Operands.push_back(
4837 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
4838 Parser.Lex();
4839 }
4840 return false;
4841}
4842
David Blaikie960ea3f2014-06-08 16:18:35 +00004843bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
4844 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004845 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004846 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004847
4848 // We have reached first instruction, module directive are now forbidden.
4849 getTargetStreamer().forbidModuleDirective();
4850
Vladimir Medic74593e62013-07-17 15:00:42 +00004851 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00004852 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00004853 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00004854 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00004855 }
Vladimir Medic64828a12013-07-16 10:07:14 +00004856 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004857 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004858
4859 // Read the remaining operands.
4860 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4861 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004862 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004863 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004864 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004865 return Error(Loc, "unexpected token in argument list");
4866 }
Toma Tabacu13964452014-09-04 13:23:44 +00004867 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004868 return true;
4869 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00004870
Jack Carterd0bd6422013-04-18 00:41:53 +00004871 while (getLexer().is(AsmToken::Comma)) {
4872 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00004873 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004874 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004875 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004876 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004877 return Error(Loc, "unexpected token in argument list");
4878 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004879 // Parse bracket and parenthesis suffixes before we iterate
4880 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00004881 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004882 return true;
4883 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00004884 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004885 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00004886 }
4887 }
Jack Carterb4dbc172012-09-05 23:34:03 +00004888 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4889 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004890 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004891 return Error(Loc, "unexpected token in argument list");
4892 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004893 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00004894 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00004895}
4896
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004897bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004898 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004899 SMLoc Loc = getLexer().getLoc();
4900 Parser.eatToEndOfStatement();
4901 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00004902}
4903
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004904bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004905 return Error(Loc, ErrorMsg);
4906}
4907
Jack Carter0b744b32012-10-04 02:29:46 +00004908bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004909 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004910 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00004911
4912 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00004913 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00004914
4915 Parser.Lex(); // Eat "noat".
4916
Jack Carterd0bd6422013-04-18 00:41:53 +00004917 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004918 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004919 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004920 return false;
4921 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004922
4923 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004924 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004925 return false;
4926}
Jack Carterd0bd6422013-04-18 00:41:53 +00004927
Jack Carter0b744b32012-10-04 02:29:46 +00004928bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00004929 // Line can be: ".set at", which sets $at to $1
4930 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00004931 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00004932 Parser.Lex(); // Eat "at".
4933
Jack Carter0b744b32012-10-04 02:29:46 +00004934 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004935 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00004936 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00004937
4938 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004939 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004940 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00004941 }
4942
4943 if (getLexer().isNot(AsmToken::Equal)) {
4944 reportParseError("unexpected token, expected equals sign");
4945 return false;
4946 }
4947 Parser.Lex(); // Eat "=".
4948
4949 if (getLexer().isNot(AsmToken::Dollar)) {
4950 if (getLexer().is(AsmToken::EndOfStatement)) {
4951 reportParseError("no register specified");
4952 return false;
4953 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00004954 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00004955 return false;
4956 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004957 }
4958 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00004959
Toma Tabacu16a74492015-02-13 10:30:57 +00004960 // Find out what "reg" is.
4961 unsigned AtRegNo;
4962 const AsmToken &Reg = Parser.getTok();
4963 if (Reg.is(AsmToken::Identifier)) {
4964 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
4965 } else if (Reg.is(AsmToken::Integer)) {
4966 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00004967 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00004968 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00004969 return false;
4970 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004971
4972 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00004973 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004974 reportParseError("invalid register");
4975 return false;
4976 }
4977 Parser.Lex(); // Eat "reg".
4978
4979 // If this is not the end of the statement, report an error.
4980 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4981 reportParseError("unexpected token, expected end of statement");
4982 return false;
4983 }
4984
4985 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
4986
4987 Parser.Lex(); // Consume the EndOfStatement.
4988 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004989}
4990
4991bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004992 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004993 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004994 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004995 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004996 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004997 return false;
4998 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004999 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00005000 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00005001 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005002 return false;
5003}
5004
5005bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005006 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005007 Parser.Lex();
5008 // If this is not the end of the statement, report an error.
5009 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005010 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005011 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00005012 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005013 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00005014 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00005015 Parser.Lex(); // Consume the EndOfStatement.
5016 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005017}
5018
5019bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005020 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00005021 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00005022 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005023 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005024 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005025 return false;
5026 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005027 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00005028 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00005029 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005030 return false;
5031}
5032
5033bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005034 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00005035 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00005036 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005037 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005038 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005039 return false;
5040 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005041 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00005042 reportParseError("`noreorder' must be set before `nomacro'");
5043 return false;
5044 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005045 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00005046 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00005047 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005048 return false;
5049}
Jack Carterd76b2372013-03-21 21:44:16 +00005050
Daniel Sanders44934432014-08-07 12:03:36 +00005051bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005052 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00005053 Parser.Lex();
5054
5055 // If this is not the end of the statement, report an error.
5056 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005057 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00005058
5059 setFeatureBits(Mips::FeatureMSA, "msa");
5060 getTargetStreamer().emitDirectiveSetMsa();
5061 return false;
5062}
5063
5064bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005065 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00005066 Parser.Lex();
5067
5068 // If this is not the end of the statement, report an error.
5069 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005070 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00005071
5072 clearFeatureBits(Mips::FeatureMSA, "msa");
5073 getTargetStreamer().emitDirectiveSetNoMsa();
5074 return false;
5075}
5076
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005077bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005078 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005079 Parser.Lex(); // Eat "nodsp".
5080
5081 // If this is not the end of the statement, report an error.
5082 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5083 reportParseError("unexpected token, expected end of statement");
5084 return false;
5085 }
5086
5087 clearFeatureBits(Mips::FeatureDSP, "dsp");
5088 getTargetStreamer().emitDirectiveSetNoDsp();
5089 return false;
5090}
5091
Toma Tabacucc2502d2014-11-04 17:18:07 +00005092bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005093 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005094 Parser.Lex(); // Eat "mips16".
5095
Jack Carter39536722014-01-22 23:08:42 +00005096 // If this is not the end of the statement, report an error.
5097 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005098 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00005099 return false;
5100 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00005101
5102 setFeatureBits(Mips::FeatureMips16, "mips16");
5103 getTargetStreamer().emitDirectiveSetMips16();
5104 Parser.Lex(); // Consume the EndOfStatement.
5105 return false;
5106}
5107
5108bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005109 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005110 Parser.Lex(); // Eat "nomips16".
5111
5112 // If this is not the end of the statement, report an error.
5113 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5114 reportParseError("unexpected token, expected end of statement");
5115 return false;
5116 }
5117
5118 clearFeatureBits(Mips::FeatureMips16, "mips16");
5119 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00005120 Parser.Lex(); // Consume the EndOfStatement.
5121 return false;
5122}
5123
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005124bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005125 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005126 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005127 // Line can be: .set fp=32
5128 // .set fp=xx
5129 // .set fp=64
5130 Parser.Lex(); // Eat fp token
5131 AsmToken Tok = Parser.getTok();
5132 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005133 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005134 return false;
5135 }
5136 Parser.Lex(); // Eat '=' token.
5137 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005138
5139 if (!parseFpABIValue(FpAbiVal, ".set"))
5140 return false;
5141
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005142 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005143 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005144 return false;
5145 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005146 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005147 Parser.Lex(); // Consume the EndOfStatement.
5148 return false;
5149}
5150
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005151bool MipsAsmParser::parseSetOddSPRegDirective() {
5152 MCAsmParser &Parser = getParser();
5153
5154 Parser.Lex(); // Eat "oddspreg".
5155 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5156 reportParseError("unexpected token, expected end of statement");
5157 return false;
5158 }
5159
5160 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5161 getTargetStreamer().emitDirectiveSetOddSPReg();
5162 return false;
5163}
5164
5165bool MipsAsmParser::parseSetNoOddSPRegDirective() {
5166 MCAsmParser &Parser = getParser();
5167
5168 Parser.Lex(); // Eat "nooddspreg".
5169 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5170 reportParseError("unexpected token, expected end of statement");
5171 return false;
5172 }
5173
5174 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5175 getTargetStreamer().emitDirectiveSetNoOddSPReg();
5176 return false;
5177}
5178
Toma Tabacu9db22db2014-09-09 10:15:38 +00005179bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005180 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005181 SMLoc Loc = getLexer().getLoc();
5182
5183 Parser.Lex();
5184 if (getLexer().isNot(AsmToken::EndOfStatement))
5185 return reportParseError("unexpected token, expected end of statement");
5186
5187 // Always keep an element on the options "stack" to prevent the user
5188 // from changing the initial options. This is how we remember them.
5189 if (AssemblerOptions.size() == 2)
5190 return reportParseError(Loc, ".set pop with no .set push");
5191
Akira Hatanakab11ef082015-11-14 06:35:56 +00005192 MCSubtargetInfo &STI = copySTI();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005193 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005194 setAvailableFeatures(
5195 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
5196 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00005197
5198 getTargetStreamer().emitDirectiveSetPop();
5199 return false;
5200}
5201
5202bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005203 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005204 Parser.Lex();
5205 if (getLexer().isNot(AsmToken::EndOfStatement))
5206 return reportParseError("unexpected token, expected end of statement");
5207
5208 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00005209 AssemblerOptions.push_back(
5210 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00005211
5212 getTargetStreamer().emitDirectiveSetPush();
5213 return false;
5214}
5215
Toma Tabacu29696502015-06-02 09:48:04 +00005216bool MipsAsmParser::parseSetSoftFloatDirective() {
5217 MCAsmParser &Parser = getParser();
5218 Parser.Lex();
5219 if (getLexer().isNot(AsmToken::EndOfStatement))
5220 return reportParseError("unexpected token, expected end of statement");
5221
5222 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5223 getTargetStreamer().emitDirectiveSetSoftFloat();
5224 return false;
5225}
5226
5227bool MipsAsmParser::parseSetHardFloatDirective() {
5228 MCAsmParser &Parser = getParser();
5229 Parser.Lex();
5230 if (getLexer().isNot(AsmToken::EndOfStatement))
5231 return reportParseError("unexpected token, expected end of statement");
5232
5233 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5234 getTargetStreamer().emitDirectiveSetHardFloat();
5235 return false;
5236}
5237
Jack Carterd76b2372013-03-21 21:44:16 +00005238bool MipsAsmParser::parseSetAssignment() {
5239 StringRef Name;
5240 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00005241 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00005242
5243 if (Parser.parseIdentifier(Name))
5244 reportParseError("expected identifier after .set");
5245
5246 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005247 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00005248 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00005249
Jack Carter3b2c96e2014-01-22 23:31:38 +00005250 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00005251 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00005252
Jim Grosbach6f482002015-05-18 18:43:14 +00005253 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00005254 Sym->setVariableValue(Value);
5255
5256 return false;
5257}
Jack Carterd0bd6422013-04-18 00:41:53 +00005258
Toma Tabacu26647792014-09-09 12:52:14 +00005259bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005260 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00005261 Parser.Lex();
5262 if (getLexer().isNot(AsmToken::EndOfStatement))
5263 return reportParseError("unexpected token, expected end of statement");
5264
5265 // Reset assembler options to their initial values.
Akira Hatanakab11ef082015-11-14 06:35:56 +00005266 MCSubtargetInfo &STI = copySTI();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005267 setAvailableFeatures(
5268 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
5269 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00005270 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
5271
5272 getTargetStreamer().emitDirectiveSetMips0();
5273 return false;
5274}
5275
Toma Tabacu85618b32014-08-19 14:22:52 +00005276bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005277 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00005278 Parser.Lex();
5279 if (getLexer().isNot(AsmToken::Equal))
5280 return reportParseError("unexpected token, expected equals sign");
5281
5282 Parser.Lex();
5283 StringRef Arch;
5284 if (Parser.parseIdentifier(Arch))
5285 return reportParseError("expected arch identifier");
5286
5287 StringRef ArchFeatureName =
5288 StringSwitch<StringRef>(Arch)
5289 .Case("mips1", "mips1")
5290 .Case("mips2", "mips2")
5291 .Case("mips3", "mips3")
5292 .Case("mips4", "mips4")
5293 .Case("mips5", "mips5")
5294 .Case("mips32", "mips32")
5295 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005296 .Case("mips32r3", "mips32r3")
5297 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005298 .Case("mips32r6", "mips32r6")
5299 .Case("mips64", "mips64")
5300 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005301 .Case("mips64r3", "mips64r3")
5302 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005303 .Case("mips64r6", "mips64r6")
5304 .Case("cnmips", "cnmips")
5305 .Case("r4000", "mips3") // This is an implementation of Mips3.
5306 .Default("");
5307
5308 if (ArchFeatureName.empty())
5309 return reportParseError("unsupported architecture");
5310
5311 selectArch(ArchFeatureName);
5312 getTargetStreamer().emitDirectiveSetArch(Arch);
5313 return false;
5314}
5315
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005316bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005317 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005318 Parser.Lex();
5319 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005320 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005321
Matheus Almeida2852af82014-04-22 10:15:54 +00005322 switch (Feature) {
5323 default:
5324 llvm_unreachable("Unimplemented feature");
5325 case Mips::FeatureDSP:
5326 setFeatureBits(Mips::FeatureDSP, "dsp");
5327 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005328 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005329 case Mips::FeatureMicroMips:
5330 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005331 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005332 case Mips::FeatureMips1:
5333 selectArch("mips1");
5334 getTargetStreamer().emitDirectiveSetMips1();
5335 break;
5336 case Mips::FeatureMips2:
5337 selectArch("mips2");
5338 getTargetStreamer().emitDirectiveSetMips2();
5339 break;
5340 case Mips::FeatureMips3:
5341 selectArch("mips3");
5342 getTargetStreamer().emitDirectiveSetMips3();
5343 break;
5344 case Mips::FeatureMips4:
5345 selectArch("mips4");
5346 getTargetStreamer().emitDirectiveSetMips4();
5347 break;
5348 case Mips::FeatureMips5:
5349 selectArch("mips5");
5350 getTargetStreamer().emitDirectiveSetMips5();
5351 break;
5352 case Mips::FeatureMips32:
5353 selectArch("mips32");
5354 getTargetStreamer().emitDirectiveSetMips32();
5355 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005356 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005357 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005358 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005359 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005360 case Mips::FeatureMips32r3:
5361 selectArch("mips32r3");
5362 getTargetStreamer().emitDirectiveSetMips32R3();
5363 break;
5364 case Mips::FeatureMips32r5:
5365 selectArch("mips32r5");
5366 getTargetStreamer().emitDirectiveSetMips32R5();
5367 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005368 case Mips::FeatureMips32r6:
5369 selectArch("mips32r6");
5370 getTargetStreamer().emitDirectiveSetMips32R6();
5371 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005372 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005373 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00005374 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005375 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005376 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005377 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005378 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005379 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005380 case Mips::FeatureMips64r3:
5381 selectArch("mips64r3");
5382 getTargetStreamer().emitDirectiveSetMips64R3();
5383 break;
5384 case Mips::FeatureMips64r5:
5385 selectArch("mips64r5");
5386 getTargetStreamer().emitDirectiveSetMips64R5();
5387 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005388 case Mips::FeatureMips64r6:
5389 selectArch("mips64r6");
5390 getTargetStreamer().emitDirectiveSetMips64R6();
5391 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005392 }
5393 return false;
5394}
5395
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005396bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005397 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005398 if (getLexer().isNot(AsmToken::Comma)) {
5399 SMLoc Loc = getLexer().getLoc();
5400 Parser.eatToEndOfStatement();
5401 return Error(Loc, ErrorStr);
5402 }
5403
Matheus Almeida2852af82014-04-22 10:15:54 +00005404 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005405 return true;
5406}
5407
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005408// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
5409// In this class, it is only used for .cprestore.
5410// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
5411// MipsTargetELFStreamer and MipsAsmParser.
5412bool MipsAsmParser::isPicAndNotNxxAbi() {
5413 return inPicMode() && !(isABI_N32() || isABI_N64());
5414}
5415
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005416bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00005417 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00005418 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005419
Toma Tabacudde4c462014-11-06 10:02:45 +00005420 if (inMips16Mode()) {
5421 reportParseError(".cpload is not supported in Mips16 mode");
5422 return false;
5423 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005424
David Blaikie960ea3f2014-06-08 16:18:35 +00005425 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00005426 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005427 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5428 reportParseError("expected register containing function address");
5429 return false;
5430 }
5431
David Blaikie960ea3f2014-06-08 16:18:35 +00005432 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
5433 if (!RegOpnd.isGPRAsmReg()) {
5434 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005435 return false;
5436 }
5437
Toma Tabacudde4c462014-11-06 10:02:45 +00005438 // If this is not the end of the statement, report an error.
5439 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5440 reportParseError("unexpected token, expected end of statement");
5441 return false;
5442 }
5443
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005444 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005445 return false;
5446}
5447
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005448bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
5449 MCAsmParser &Parser = getParser();
5450
5451 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
5452 // is used in non-PIC mode.
5453
5454 if (inMips16Mode()) {
5455 reportParseError(".cprestore is not supported in Mips16 mode");
5456 return false;
5457 }
5458
5459 // Get the stack offset value.
5460 const MCExpr *StackOffset;
5461 int64_t StackOffsetVal;
5462 if (Parser.parseExpression(StackOffset)) {
5463 reportParseError("expected stack offset value");
5464 return false;
5465 }
5466
5467 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
5468 reportParseError("stack offset is not an absolute expression");
5469 return false;
5470 }
5471
5472 if (StackOffsetVal < 0) {
5473 Warning(Loc, ".cprestore with negative stack offset has no effect");
5474 IsCpRestoreSet = false;
5475 } else {
5476 IsCpRestoreSet = true;
5477 CpRestoreOffset = StackOffsetVal;
5478 }
5479
5480 // If this is not the end of the statement, report an error.
5481 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5482 reportParseError("unexpected token, expected end of statement");
5483 return false;
5484 }
5485
5486 // Store the $gp on the stack.
5487 SmallVector<MCInst, 3> StoreInsts;
5488 createCpRestoreMemOp(false /*IsLoad*/, CpRestoreOffset /*StackOffset*/, Loc,
5489 StoreInsts);
5490
5491 getTargetStreamer().emitDirectiveCpRestore(StoreInsts, CpRestoreOffset);
5492 Parser.Lex(); // Consume the EndOfStatement.
5493 return false;
5494}
5495
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005496bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005497 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005498 unsigned FuncReg;
5499 unsigned Save;
5500 bool SaveIsReg = true;
5501
Matheus Almeida7e815762014-06-18 13:08:59 +00005502 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005503 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005504 if (ResTy == MatchOperand_NoMatch) {
5505 reportParseError("expected register containing function address");
5506 Parser.eatToEndOfStatement();
5507 return false;
5508 }
5509
5510 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5511 if (!FuncRegOpnd.isGPRAsmReg()) {
5512 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
5513 Parser.eatToEndOfStatement();
5514 return false;
5515 }
5516
5517 FuncReg = FuncRegOpnd.getGPR32Reg();
5518 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005519
Toma Tabacu65f10572014-09-16 15:00:52 +00005520 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005521 return true;
5522
Toma Tabacu13964452014-09-04 13:23:44 +00005523 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005524 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00005525 const MCExpr *OffsetExpr;
5526 int64_t OffsetVal;
5527 SMLoc ExprLoc = getLexer().getLoc();
5528
5529 if (Parser.parseExpression(OffsetExpr) ||
5530 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
5531 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00005532 Parser.eatToEndOfStatement();
5533 return false;
5534 }
Daniel Sanders5d796282015-09-21 09:26:55 +00005535
5536 Save = OffsetVal;
5537 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00005538 } else {
5539 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5540 if (!SaveOpnd.isGPRAsmReg()) {
5541 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
5542 Parser.eatToEndOfStatement();
5543 return false;
5544 }
5545 Save = SaveOpnd.getGPR32Reg();
5546 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005547
Toma Tabacu65f10572014-09-16 15:00:52 +00005548 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005549 return true;
5550
Toma Tabacu8874eac2015-02-18 13:46:53 +00005551 const MCExpr *Expr;
5552 if (Parser.parseExpression(Expr)) {
5553 reportParseError("expected expression");
5554 return false;
5555 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005556
Toma Tabacu8874eac2015-02-18 13:46:53 +00005557 if (Expr->getKind() != MCExpr::SymbolRef) {
5558 reportParseError("expected symbol");
5559 return false;
5560 }
5561 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
5562
Daniel Sandersf173dda2015-09-22 10:50:09 +00005563 CpSaveLocation = Save;
5564 CpSaveLocationIsRegister = SaveIsReg;
5565
Toma Tabacu8874eac2015-02-18 13:46:53 +00005566 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
5567 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005568 return false;
5569}
5570
Daniel Sandersf173dda2015-09-22 10:50:09 +00005571bool MipsAsmParser::parseDirectiveCPReturn() {
5572 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
5573 CpSaveLocationIsRegister);
5574 return false;
5575}
5576
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005577bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005578 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005579 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5580 const AsmToken &Tok = Parser.getTok();
5581
5582 if (Tok.getString() == "2008") {
5583 Parser.Lex();
5584 getTargetStreamer().emitDirectiveNaN2008();
5585 return false;
5586 } else if (Tok.getString() == "legacy") {
5587 Parser.Lex();
5588 getTargetStreamer().emitDirectiveNaNLegacy();
5589 return false;
5590 }
5591 }
5592 // If we don't recognize the option passed to the .nan
5593 // directive (e.g. no option or unknown option), emit an error.
5594 reportParseError("invalid option in .nan directive");
5595 return false;
5596}
5597
Jack Carter0b744b32012-10-04 02:29:46 +00005598bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005599 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005600 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00005601 const AsmToken &Tok = Parser.getTok();
5602
5603 if (Tok.getString() == "noat") {
5604 return parseSetNoAtDirective();
5605 } else if (Tok.getString() == "at") {
5606 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00005607 } else if (Tok.getString() == "arch") {
5608 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005609 } else if (Tok.getString() == "fp") {
5610 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005611 } else if (Tok.getString() == "oddspreg") {
5612 return parseSetOddSPRegDirective();
5613 } else if (Tok.getString() == "nooddspreg") {
5614 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005615 } else if (Tok.getString() == "pop") {
5616 return parseSetPopDirective();
5617 } else if (Tok.getString() == "push") {
5618 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00005619 } else if (Tok.getString() == "reorder") {
5620 return parseSetReorderDirective();
5621 } else if (Tok.getString() == "noreorder") {
5622 return parseSetNoReorderDirective();
5623 } else if (Tok.getString() == "macro") {
5624 return parseSetMacroDirective();
5625 } else if (Tok.getString() == "nomacro") {
5626 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00005627 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00005628 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005629 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00005630 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005631 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00005632 getTargetStreamer().emitDirectiveSetNoMicroMips();
5633 Parser.eatToEndOfStatement();
5634 return false;
5635 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005636 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00005637 } else if (Tok.getString() == "mips0") {
5638 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00005639 } else if (Tok.getString() == "mips1") {
5640 return parseSetFeature(Mips::FeatureMips1);
5641 } else if (Tok.getString() == "mips2") {
5642 return parseSetFeature(Mips::FeatureMips2);
5643 } else if (Tok.getString() == "mips3") {
5644 return parseSetFeature(Mips::FeatureMips3);
5645 } else if (Tok.getString() == "mips4") {
5646 return parseSetFeature(Mips::FeatureMips4);
5647 } else if (Tok.getString() == "mips5") {
5648 return parseSetFeature(Mips::FeatureMips5);
5649 } else if (Tok.getString() == "mips32") {
5650 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00005651 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005652 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005653 } else if (Tok.getString() == "mips32r3") {
5654 return parseSetFeature(Mips::FeatureMips32r3);
5655 } else if (Tok.getString() == "mips32r5") {
5656 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005657 } else if (Tok.getString() == "mips32r6") {
5658 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005659 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005660 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005661 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005662 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005663 } else if (Tok.getString() == "mips64r3") {
5664 return parseSetFeature(Mips::FeatureMips64r3);
5665 } else if (Tok.getString() == "mips64r5") {
5666 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005667 } else if (Tok.getString() == "mips64r6") {
5668 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00005669 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005670 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005671 } else if (Tok.getString() == "nodsp") {
5672 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00005673 } else if (Tok.getString() == "msa") {
5674 return parseSetMsaDirective();
5675 } else if (Tok.getString() == "nomsa") {
5676 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00005677 } else if (Tok.getString() == "softfloat") {
5678 return parseSetSoftFloatDirective();
5679 } else if (Tok.getString() == "hardfloat") {
5680 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00005681 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00005682 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00005683 parseSetAssignment();
5684 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005685 }
Jack Carter07c818d2013-01-25 01:31:34 +00005686
Jack Carter0b744b32012-10-04 02:29:46 +00005687 return true;
5688}
5689
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005690/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00005691/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005692bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005693 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005694 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5695 for (;;) {
5696 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005697 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00005698 return true;
5699
5700 getParser().getStreamer().EmitValue(Value, Size);
5701
5702 if (getLexer().is(AsmToken::EndOfStatement))
5703 break;
5704
Jack Carter07c818d2013-01-25 01:31:34 +00005705 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005706 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00005707 Parser.Lex();
5708 }
5709 }
5710
5711 Parser.Lex();
5712 return false;
5713}
5714
Vladimir Medic4c299852013-11-06 11:27:05 +00005715/// parseDirectiveGpWord
5716/// ::= .gpword local_sym
5717bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005718 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00005719 const MCExpr *Value;
5720 // EmitGPRel32Value requires an expression, so we are using base class
5721 // method to evaluate the expression.
5722 if (getParser().parseExpression(Value))
5723 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00005724 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00005725
Vladimir Medice10c1122013-11-13 13:18:04 +00005726 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005727 return Error(getLexer().getLoc(),
5728 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00005729 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00005730 return false;
5731}
5732
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005733/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00005734/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005735bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005736 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005737 const MCExpr *Value;
5738 // EmitGPRel64Value requires an expression, so we are using base class
5739 // method to evaluate the expression.
5740 if (getParser().parseExpression(Value))
5741 return true;
5742 getParser().getStreamer().EmitGPRel64Value(Value);
5743
5744 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005745 return Error(getLexer().getLoc(),
5746 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00005747 Parser.Lex(); // Eat EndOfStatement token.
5748 return false;
5749}
5750
Jack Carter0cd3c192014-01-06 23:27:31 +00005751bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005752 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00005753 // Get the option token.
5754 AsmToken Tok = Parser.getTok();
5755 // At the moment only identifiers are supported.
5756 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005757 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00005758 Parser.eatToEndOfStatement();
5759 return false;
5760 }
5761
5762 StringRef Option = Tok.getIdentifier();
5763
5764 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005765 // MipsAsmParser needs to know if the current PIC mode changes.
5766 IsPicEnabled = false;
5767
Jack Carter0cd3c192014-01-06 23:27:31 +00005768 getTargetStreamer().emitDirectiveOptionPic0();
5769 Parser.Lex();
5770 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5771 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005772 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005773 Parser.eatToEndOfStatement();
5774 }
5775 return false;
5776 }
5777
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005778 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005779 // MipsAsmParser needs to know if the current PIC mode changes.
5780 IsPicEnabled = true;
5781
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005782 getTargetStreamer().emitDirectiveOptionPic2();
5783 Parser.Lex();
5784 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5785 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005786 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005787 Parser.eatToEndOfStatement();
5788 }
5789 return false;
5790 }
5791
Jack Carter0cd3c192014-01-06 23:27:31 +00005792 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00005793 Warning(Parser.getTok().getLoc(),
5794 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00005795 Parser.eatToEndOfStatement();
5796 return false;
5797}
5798
Toma Tabacu9ca50962015-04-16 09:53:47 +00005799/// parseInsnDirective
5800/// ::= .insn
5801bool MipsAsmParser::parseInsnDirective() {
5802 // If this is not the end of the statement, report an error.
5803 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5804 reportParseError("unexpected token, expected end of statement");
5805 return false;
5806 }
5807
5808 // The actual label marking happens in
5809 // MipsELFStreamer::createPendingLabelRelocs().
5810 getTargetStreamer().emitDirectiveInsn();
5811
5812 getParser().Lex(); // Eat EndOfStatement token.
5813 return false;
5814}
5815
Simon Atanasyanbe186202016-02-11 06:45:54 +00005816/// parseSSectionDirective
5817/// ::= .sbss
5818/// ::= .sdata
5819bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) {
5820 // If this is not the end of the statement, report an error.
5821 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5822 reportParseError("unexpected token, expected end of statement");
5823 return false;
5824 }
5825
5826 MCSection *ELFSection = getContext().getELFSection(
5827 Section, Type, ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL);
5828 getParser().getStreamer().SwitchSection(ELFSection);
5829
5830 getParser().Lex(); // Eat EndOfStatement token.
5831 return false;
5832}
5833
Daniel Sanders7e527422014-07-10 13:38:23 +00005834/// parseDirectiveModule
5835/// ::= .module oddspreg
5836/// ::= .module nooddspreg
5837/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00005838/// ::= .module softfloat
5839/// ::= .module hardfloat
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005840bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005841 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005842 MCAsmLexer &Lexer = getLexer();
5843 SMLoc L = Lexer.getLoc();
5844
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00005845 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005846 // TODO : get a better message.
5847 reportParseError(".module directive must appear before any code");
5848 return false;
5849 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005850
Toma Tabacuc405c822015-01-23 10:40:19 +00005851 StringRef Option;
5852 if (Parser.parseIdentifier(Option)) {
5853 reportParseError("expected .module option identifier");
5854 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005855 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005856
Toma Tabacuc405c822015-01-23 10:40:19 +00005857 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005858 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005859
Toma Tabacu3c499582015-06-25 10:56:57 +00005860 // Synchronize the abiflags information with the FeatureBits information we
5861 // changed above.
5862 getTargetStreamer().updateABIInfo(*this);
5863
5864 // If printing assembly, use the recently updated abiflags information.
5865 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5866 // emitted at the end).
5867 getTargetStreamer().emitDirectiveModuleOddSPReg();
5868
Toma Tabacuc405c822015-01-23 10:40:19 +00005869 // If this is not the end of the statement, report an error.
5870 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5871 reportParseError("unexpected token, expected end of statement");
5872 return false;
5873 }
5874
5875 return false; // parseDirectiveModule has finished successfully.
5876 } else if (Option == "nooddspreg") {
5877 if (!isABI_O32()) {
5878 Error(L, "'.module nooddspreg' requires the O32 ABI");
5879 return false;
5880 }
5881
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005882 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005883
Toma Tabacu3c499582015-06-25 10:56:57 +00005884 // Synchronize the abiflags information with the FeatureBits information we
5885 // changed above.
5886 getTargetStreamer().updateABIInfo(*this);
5887
5888 // If printing assembly, use the recently updated abiflags information.
5889 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5890 // emitted at the end).
5891 getTargetStreamer().emitDirectiveModuleOddSPReg();
5892
Toma Tabacuc405c822015-01-23 10:40:19 +00005893 // If this is not the end of the statement, report an error.
5894 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5895 reportParseError("unexpected token, expected end of statement");
5896 return false;
5897 }
5898
5899 return false; // parseDirectiveModule has finished successfully.
5900 } else if (Option == "fp") {
5901 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00005902 } else if (Option == "softfloat") {
5903 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5904
5905 // Synchronize the ABI Flags information with the FeatureBits information we
5906 // updated above.
5907 getTargetStreamer().updateABIInfo(*this);
5908
5909 // If printing assembly, use the recently updated ABI Flags information.
5910 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5911 // emitted later).
5912 getTargetStreamer().emitDirectiveModuleSoftFloat();
5913
5914 // 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 == "hardfloat") {
5922 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5923
5924 // Synchronize the ABI Flags information with the FeatureBits information we
5925 // updated above.
5926 getTargetStreamer().updateABIInfo(*this);
5927
5928 // If printing assembly, use the recently updated ABI Flags information.
5929 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5930 // emitted later).
5931 getTargetStreamer().emitDirectiveModuleHardFloat();
5932
5933 // If this is not the end of the statement, report an error.
5934 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5935 reportParseError("unexpected token, expected end of statement");
5936 return false;
5937 }
5938
5939 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00005940 } else {
5941 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
5942 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005943}
5944
5945/// parseDirectiveModuleFP
5946/// ::= =32
5947/// ::= =xx
5948/// ::= =64
5949bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005950 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005951 MCAsmLexer &Lexer = getLexer();
5952
5953 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005954 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005955 return false;
5956 }
5957 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005958
Daniel Sanders7e527422014-07-10 13:38:23 +00005959 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005960 if (!parseFpABIValue(FpABI, ".module"))
5961 return false;
5962
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005963 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005964 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005965 return false;
5966 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005967
Toma Tabacua64e5402015-06-25 12:44:38 +00005968 // Synchronize the abiflags information with the FeatureBits information we
5969 // changed above.
5970 getTargetStreamer().updateABIInfo(*this);
5971
5972 // If printing assembly, use the recently updated abiflags information.
5973 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5974 // emitted at the end).
5975 getTargetStreamer().emitDirectiveModuleFP();
5976
Daniel Sanders7e527422014-07-10 13:38:23 +00005977 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005978 return false;
5979}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005980
Daniel Sanders7e527422014-07-10 13:38:23 +00005981bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005982 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005983 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005984 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005985 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005986
5987 if (Lexer.is(AsmToken::Identifier)) {
5988 StringRef Value = Parser.getTok().getString();
5989 Parser.Lex();
5990
5991 if (Value != "xx") {
5992 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5993 return false;
5994 }
5995
5996 if (!isABI_O32()) {
5997 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
5998 return false;
5999 }
6000
Daniel Sanders7e527422014-07-10 13:38:23 +00006001 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006002 if (ModuleLevelOptions) {
6003 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6004 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6005 } else {
6006 setFeatureBits(Mips::FeatureFPXX, "fpxx");
6007 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
6008 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006009 return true;
6010 }
6011
6012 if (Lexer.is(AsmToken::Integer)) {
6013 unsigned Value = Parser.getTok().getIntVal();
6014 Parser.Lex();
6015
6016 if (Value != 32 && Value != 64) {
6017 reportParseError("unsupported value, expected 'xx', '32' or '64'");
6018 return false;
6019 }
6020
6021 if (Value == 32) {
6022 if (!isABI_O32()) {
6023 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
6024 return false;
6025 }
6026
Daniel Sanders7e527422014-07-10 13:38:23 +00006027 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006028 if (ModuleLevelOptions) {
6029 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6030 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6031 } else {
6032 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
6033 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
6034 }
Toma Tabacua64e5402015-06-25 12:44:38 +00006035 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00006036 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006037 if (ModuleLevelOptions) {
6038 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6039 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6040 } else {
6041 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
6042 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
6043 }
Toma Tabacua64e5402015-06-25 12:44:38 +00006044 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006045
Daniel Sanders7e527422014-07-10 13:38:23 +00006046 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006047 }
6048
6049 return false;
6050}
6051
Jack Carter0b744b32012-10-04 02:29:46 +00006052bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006053 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00006054 StringRef IDVal = DirectiveID.getString();
6055
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006056 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00006057 return parseDirectiveCpLoad(DirectiveID.getLoc());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006058 if (IDVal == ".cprestore")
6059 return parseDirectiveCpRestore(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00006060 if (IDVal == ".dword") {
6061 parseDataDirective(8, DirectiveID.getLoc());
6062 return false;
6063 }
Jack Carterd0bd6422013-04-18 00:41:53 +00006064 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006065 StringRef SymbolName;
6066
6067 if (Parser.parseIdentifier(SymbolName)) {
6068 reportParseError("expected identifier after .ent");
6069 return false;
6070 }
6071
6072 // There's an undocumented extension that allows an integer to
6073 // follow the name of the procedure which AFAICS is ignored by GAS.
6074 // Example: .ent foo,2
6075 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6076 if (getLexer().isNot(AsmToken::Comma)) {
6077 // Even though we accept this undocumented extension for compatibility
6078 // reasons, the additional integer argument does not actually change
6079 // the behaviour of the '.ent' directive, so we would like to discourage
6080 // its use. We do this by not referring to the extended version in
6081 // error messages which are not directly related to its use.
6082 reportParseError("unexpected token, expected end of statement");
6083 return false;
6084 }
6085 Parser.Lex(); // Eat the comma.
6086 const MCExpr *DummyNumber;
6087 int64_t DummyNumberVal;
6088 // If the user was explicitly trying to use the extended version,
6089 // we still give helpful extension-related error messages.
6090 if (Parser.parseExpression(DummyNumber)) {
6091 reportParseError("expected number after comma");
6092 return false;
6093 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00006094 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006095 reportParseError("expected an absolute expression after comma");
6096 return false;
6097 }
6098 }
6099
6100 // If this is not the end of the statement, report an error.
6101 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6102 reportParseError("unexpected token, expected end of statement");
6103 return false;
6104 }
6105
Jim Grosbach6f482002015-05-18 18:43:14 +00006106 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006107
6108 getTargetStreamer().emitDirectiveEnt(*Sym);
6109 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006110 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006111 return false;
6112 }
6113
Jack Carter07c818d2013-01-25 01:31:34 +00006114 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006115 StringRef SymbolName;
6116
6117 if (Parser.parseIdentifier(SymbolName)) {
6118 reportParseError("expected identifier after .end");
6119 return false;
6120 }
6121
6122 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6123 reportParseError("unexpected token, expected end of statement");
6124 return false;
6125 }
6126
6127 if (CurrentFn == nullptr) {
6128 reportParseError(".end used without .ent");
6129 return false;
6130 }
6131
6132 if ((SymbolName != CurrentFn->getName())) {
6133 reportParseError(".end symbol does not match .ent symbol");
6134 return false;
6135 }
6136
6137 getTargetStreamer().emitDirectiveEnd(SymbolName);
6138 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006139 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006140 return false;
6141 }
6142
Jack Carter07c818d2013-01-25 01:31:34 +00006143 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006144 // .frame $stack_reg, frame_size_in_bytes, $return_reg
6145 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00006146 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006147 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6148 reportParseError("expected stack register");
6149 return false;
6150 }
6151
6152 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6153 if (!StackRegOpnd.isGPRAsmReg()) {
6154 reportParseError(StackRegOpnd.getStartLoc(),
6155 "expected general purpose register");
6156 return false;
6157 }
6158 unsigned StackReg = StackRegOpnd.getGPR32Reg();
6159
6160 if (Parser.getTok().is(AsmToken::Comma))
6161 Parser.Lex();
6162 else {
6163 reportParseError("unexpected token, expected comma");
6164 return false;
6165 }
6166
6167 // Parse the frame size.
6168 const MCExpr *FrameSize;
6169 int64_t FrameSizeVal;
6170
6171 if (Parser.parseExpression(FrameSize)) {
6172 reportParseError("expected frame size value");
6173 return false;
6174 }
6175
Jim Grosbach13760bd2015-05-30 01:25:56 +00006176 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006177 reportParseError("frame size not an absolute expression");
6178 return false;
6179 }
6180
6181 if (Parser.getTok().is(AsmToken::Comma))
6182 Parser.Lex();
6183 else {
6184 reportParseError("unexpected token, expected comma");
6185 return false;
6186 }
6187
6188 // Parse the return register.
6189 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00006190 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006191 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6192 reportParseError("expected return register");
6193 return false;
6194 }
6195
6196 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6197 if (!ReturnRegOpnd.isGPRAsmReg()) {
6198 reportParseError(ReturnRegOpnd.getStartLoc(),
6199 "expected general purpose register");
6200 return false;
6201 }
6202
6203 // If this is not the end of the statement, report an error.
6204 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6205 reportParseError("unexpected token, expected end of statement");
6206 return false;
6207 }
6208
6209 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
6210 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006211 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006212 return false;
6213 }
6214
Jack Carter07c818d2013-01-25 01:31:34 +00006215 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00006216 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00006217 }
6218
Daniel Sandersd97a6342014-08-13 10:07:34 +00006219 if (IDVal == ".mask" || IDVal == ".fmask") {
6220 // .mask bitmask, frame_offset
6221 // bitmask: One bit for each register used.
6222 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
6223 // first register is expected to be saved.
6224 // Examples:
6225 // .mask 0x80000000, -4
6226 // .fmask 0x80000000, -4
6227 //
Jack Carterbe332172012-09-07 00:48:02 +00006228
Daniel Sandersd97a6342014-08-13 10:07:34 +00006229 // Parse the bitmask
6230 const MCExpr *BitMask;
6231 int64_t BitMaskVal;
6232
6233 if (Parser.parseExpression(BitMask)) {
6234 reportParseError("expected bitmask value");
6235 return false;
6236 }
6237
Jim Grosbach13760bd2015-05-30 01:25:56 +00006238 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006239 reportParseError("bitmask not an absolute expression");
6240 return false;
6241 }
6242
6243 if (Parser.getTok().is(AsmToken::Comma))
6244 Parser.Lex();
6245 else {
6246 reportParseError("unexpected token, expected comma");
6247 return false;
6248 }
6249
6250 // Parse the frame_offset
6251 const MCExpr *FrameOffset;
6252 int64_t FrameOffsetVal;
6253
6254 if (Parser.parseExpression(FrameOffset)) {
6255 reportParseError("expected frame offset value");
6256 return false;
6257 }
6258
Jim Grosbach13760bd2015-05-30 01:25:56 +00006259 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006260 reportParseError("frame offset not an absolute expression");
6261 return false;
6262 }
6263
6264 // If this is not the end of the statement, report an error.
6265 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6266 reportParseError("unexpected token, expected end of statement");
6267 return false;
6268 }
6269
6270 if (IDVal == ".mask")
6271 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
6272 else
6273 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00006274 return false;
6275 }
6276
Matheus Almeida0051f2d2014-04-16 15:48:55 +00006277 if (IDVal == ".nan")
6278 return parseDirectiveNaN();
6279
Jack Carter07c818d2013-01-25 01:31:34 +00006280 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00006281 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00006282 return false;
6283 }
6284
Rafael Espindolab59fb732014-03-28 18:50:26 +00006285 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00006286 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00006287 return false;
6288 }
6289
Jack Carter07c818d2013-01-25 01:31:34 +00006290 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00006291 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00006292 return false;
6293 }
6294
Scott Egertond1aeb052016-02-15 16:11:51 +00006295 if (IDVal == ".hword") {
6296 parseDataDirective(2, DirectiveID.getLoc());
6297 return false;
6298 }
6299
Jack Carter0cd3c192014-01-06 23:27:31 +00006300 if (IDVal == ".option")
6301 return parseDirectiveOption();
6302
6303 if (IDVal == ".abicalls") {
6304 getTargetStreamer().emitDirectiveAbiCalls();
6305 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006306 Error(Parser.getTok().getLoc(),
6307 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00006308 // Clear line
6309 Parser.eatToEndOfStatement();
6310 }
6311 return false;
6312 }
6313
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006314 if (IDVal == ".cpsetup")
6315 return parseDirectiveCPSetup();
6316
Daniel Sandersf173dda2015-09-22 10:50:09 +00006317 if (IDVal == ".cpreturn")
6318 return parseDirectiveCPReturn();
6319
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006320 if (IDVal == ".module")
6321 return parseDirectiveModule();
6322
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00006323 if (IDVal == ".llvm_internal_mips_reallow_module_directive")
6324 return parseInternalDirectiveReallowModule();
6325
Toma Tabacu9ca50962015-04-16 09:53:47 +00006326 if (IDVal == ".insn")
6327 return parseInsnDirective();
6328
Simon Atanasyanbe186202016-02-11 06:45:54 +00006329 if (IDVal == ".sbss")
6330 return parseSSectionDirective(IDVal, ELF::SHT_NOBITS);
6331 if (IDVal == ".sdata")
6332 return parseSSectionDirective(IDVal, ELF::SHT_PROGBITS);
6333
Rafael Espindola870c4e92012-01-11 03:56:41 +00006334 return true;
6335}
6336
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00006337bool MipsAsmParser::parseInternalDirectiveReallowModule() {
6338 // If this is not the end of the statement, report an error.
6339 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6340 reportParseError("unexpected token, expected end of statement");
6341 return false;
6342 }
6343
6344 getTargetStreamer().reallowModuleDirective();
6345
6346 getParser().Lex(); // Eat EndOfStatement token.
6347 return false;
6348}
6349
Rafael Espindola870c4e92012-01-11 03:56:41 +00006350extern "C" void LLVMInitializeMipsAsmParser() {
6351 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
6352 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
6353 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
6354 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
6355}
Jack Carterb4dbc172012-09-05 23:34:03 +00006356
6357#define GET_REGISTER_MATCHER
6358#define GET_MATCHER_IMPLEMENTATION
6359#include "MipsGenAsmMatcher.inc"